revise network system

This commit is contained in:
Eduardo Bart 2011-08-15 21:30:31 -03:00
parent be15b1820d
commit f87b475f49
26 changed files with 291 additions and 242 deletions

View File

@ -77,6 +77,7 @@ SET(SOURCES
src/framework/thirdparty/apngloader.cpp src/framework/thirdparty/apngloader.cpp
# framework net # framework net
src/framework/net/networkmanager.cpp
src/framework/net/connection.cpp src/framework/net/connection.cpp
src/framework/net/inputmessage.cpp src/framework/net/inputmessage.cpp
src/framework/net/outputmessage.cpp src/framework/net/outputmessage.cpp

View File

@ -47,4 +47,7 @@
#include "util/rect.h" #include "util/rect.h"
#include "util/size.h" #include "util/size.h"
// easy typing for _1, _2, ...
using namespace std::placeholders;
#endif #endif

View File

@ -6,9 +6,6 @@
void LuaInterface::registerFunctions() void LuaInterface::registerFunctions()
{ {
// easy typing _1, _2, ...
using namespace std::placeholders;
// UIWidget // UIWidget
g_lua.registerClass<UIWidget>(); g_lua.registerClass<UIWidget>();
g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create); g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create);

View File

@ -1,125 +1,147 @@
#include "connection.h" #include "connection.h"
#include "networkmanager.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <boost/asio.hpp>
static asio::io_service ioService; asio::io_service g_ioService;
Connection::Connection() : Connection::Connection() :
m_timer(ioService), m_readTimer(g_ioService),
m_resolver(ioService), m_writeTimer(g_ioService),
m_socket(ioService) m_resolver(g_ioService),
m_socket(g_ioService)
{ {
} m_connected = false;
Connection::~Connection()
{
disconnect();
} }
void Connection::poll() void Connection::poll()
{ {
ioService.poll(); g_ioService.poll();
ioService.reset(); g_ioService.reset();
} }
void Connection::connect(const std::string& host, uint16 port, const ConnectCallback& connectCallback) void Connection::terminate()
{ {
g_ioService.stop();
}
void Connection::connect(const std::string& host, uint16 port, const SimpleCallback& connectCallback)
{
m_connected = false;
m_connectCallback = connectCallback; m_connectCallback = connectCallback;
asio::ip::tcp::resolver::query query(host, fw::unsafe_cast<std::string>(port)); asio::ip::tcp::resolver::query query(host, fw::unsafe_cast<std::string>(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_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); 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::async_write(m_socket,
asio::buffer(buffer, size), asio::buffer(buffer, size),
std::bind(&Connection::onSend, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); std::bind(&Connection::onWrite, shared_from_this(), _1, _2));
m_timer.expires_from_now(boost::posix_time::seconds(2)); m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); 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_recvCallback = callback;
m_recvSize = bytes; m_recvSize = bytes;
asio::async_read(m_socket, asio::async_read(m_socket,
asio::buffer(m_recvBuffer, bytes), asio::buffer(m_recvBuffer, bytes),
std::bind(&Connection::onRecv, shared_from_this(), std::placeholders::_1)); std::bind(&Connection::onRecv, shared_from_this(), _1));
if(timeout > 0) { m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
m_timer.expires_from_now(boost::posix_time::seconds(timeout)); m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), _1));
m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); }
}
void Connection::onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator)
{
m_readTimer.cancel();
if(!error) {
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, shared_from_this(), _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_readTimer.cancel();
m_connected = true;
if(!error) {
if(m_connectCallback)
g_dispatcher.addEvent(m_connectCallback);
} else
handleError(error);
}
void Connection::onWrite(const boost::system::error_code& error, size_t)
{
m_writeTimer.cancel();
if(error)
handleError(error);
}
void Connection::onRecv(const boost::system::error_code& error)
{
m_readTimer.cancel();
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) void Connection::onTimeout(const boost::system::error_code& error)
{ {
if(error != asio::error::operation_aborted) if(error != asio::error::operation_aborted)
handleError(error);
}
void Connection::handleError(const boost::system::error_code& error)
{
logTraceDebug(error.message());
close();
if(m_errorCallback)
g_dispatcher.addEvent(std::bind(m_errorCallback, error)); g_dispatcher.addEvent(std::bind(m_errorCallback, error));
} }
void Connection::onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator)
{
m_timer.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));
m_timer.expires_from_now(boost::posix_time::seconds(2));
m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1));
}
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);
}
void Connection::onSend(const boost::system::error_code& error, size_t)
{
m_timer.cancel();
if(error) {
if(m_errorCallback)
g_dispatcher.addEvent(std::bind(m_errorCallback, error));
return;
}
}
void Connection::onRecv(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_recvCallback)
g_dispatcher.addEvent(std::bind(m_recvCallback, m_recvBuffer, m_recvSize));
}

View File

@ -8,40 +8,49 @@ class Connection : public std::enable_shared_from_this<Connection>, boost::nonco
{ {
typedef std::function<void(boost::system::error_code&)> ErrorCallback; typedef std::function<void(boost::system::error_code&)> ErrorCallback;
typedef std::function<void(uint8*, uint16)> RecvCallback; typedef std::function<void(uint8*, uint16)> RecvCallback;
typedef std::function<void()> ConnectCallback;
enum {
READ_TIMEOUT = 10,
WRITE_TIMEOUT = 10
};
public: public:
Connection(); Connection();
virtual ~Connection();
static void init();
static void poll(); static void poll();
static void terminate();
void connect(const std::string& host, uint16 port, const ConnectCallback& connectCallback); void connect(const std::string& host, uint16 port, const SimpleCallback& connectCallback);
void disconnect(); void close();
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 setErrorCallback(const ErrorCallback& errorCallback) { m_errorCallback = errorCallback; }
void setRecvCallback(const RecvCallback& recvCallback) { m_recvCallback = recvCallback; }
bool isConnected() const { return m_connected; }
private: private:
void onTimeout(const boost::system::error_code& error);
void onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator); void onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator);
void onConnect(const boost::system::error_code& error); 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 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; 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::resolver m_resolver;
asio::ip::tcp::socket m_socket; asio::ip::tcp::socket m_socket;
uint8 m_recvBuffer[65538]; uint8 m_recvBuffer[65538];
uint16 m_recvSize; uint16 m_recvSize;
RecvCallback m_recvCallback; bool m_connected;
}; };
#endif #endif

View File

@ -1,10 +1,9 @@
#include "protocol.h" #include "protocol.h"
#include "connection.h" #include "connection.h"
Protocol::Protocol() : Protocol::Protocol() : m_connection(new Connection)
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_xteaEncryptionEnabled = false;
m_checksumEnabled = true; 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())); m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol()));
} }
void Protocol::disconnect()
{
m_connection->close();
}
void Protocol::send(OutputMessage& outputMessage) void Protocol::send(OutputMessage& outputMessage)
{ {
// Encrypt // encrypt
if(m_xteaEncryptionEnabled) if(m_xteaEncryptionEnabled)
xteaEncrypt(outputMessage); xteaEncrypt(outputMessage);
// Set checksum // set checksum
uint32 checksum = getAdlerChecksum(outputMessage.getBuffer() + OutputMessage::DATA_POS, outputMessage.getMessageSize()); uint32 checksum = getAdlerChecksum(outputMessage.getBuffer() + OutputMessage::DATA_POS, outputMessage.getMessageSize());
outputMessage.setWritePos(OutputMessage::CHECKSUM_POS); outputMessage.setWritePos(OutputMessage::CHECKSUM_POS);
outputMessage.addU32(checksum); outputMessage.addU32(checksum);
// Set size // set size
uint16 messageSize = outputMessage.getMessageSize(); uint16 messageSize = outputMessage.getMessageSize();
outputMessage.setWritePos(OutputMessage::HEADER_POS); outputMessage.setWritePos(OutputMessage::HEADER_POS);
outputMessage.addU16(messageSize); outputMessage.addU16(messageSize);
// Send // send
m_connection->send(outputMessage.getBuffer(), outputMessage.getMessageSize()); m_connection->write(outputMessage.getBuffer(), outputMessage.getMessageSize());
} }
void Protocol::recv() void Protocol::recv()
{ {
m_inputMessage.reset(); 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) void Protocol::internalRecvHeader(uint8* buffer, uint16 size)
{ {
memcpy(m_inputMessage.getBuffer() + InputMessage::HEADER_POS, buffer, size); memcpy(m_inputMessage.getBuffer() + InputMessage::HEADER_POS, buffer, size);
// read message size
uint16 dataSize = m_inputMessage.getU16(); uint16 dataSize = m_inputMessage.getU16();
m_inputMessage.setMessageSize(dataSize); 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) 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); uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH);
if(m_inputMessage.getU32() != checksum) { if(m_inputMessage.getU32() != checksum) {
// error // error
logError("Checksum is invalid."); logError("ERROR: got a network message with invalid checksum");
return; return;
} }
} }
@ -70,27 +76,12 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
onRecv(m_inputMessage); 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) bool Protocol::xteaDecrypt(InputMessage& inputMessage)
{ {
// FIXME: this function has not been tested yet // FIXME: this function has not been tested yet
uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH; uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH;
if(messageSize % 8 != 0) { if(messageSize % 8 != 0) {
logDebug("not valid encrypted message size"); logError("ERROR: invalid encrypted network message");
return false; return false;
} }
@ -113,7 +104,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
int tmp = inputMessage.getU16(); int tmp = inputMessage.getU16();
if(tmp > inputMessage.getMessageSize() - 4) { if(tmp > inputMessage.getMessageSize() - 4) {
logDebug("not valid unencrypted message size"); logDebug("ERROR: invalid decrypted a network message");
return false; return false;
} }

View File

@ -13,14 +13,17 @@ public:
Protocol(); Protocol();
void connect(const std::string& host, uint16 port); void connect(const std::string& host, uint16 port);
void disconnect();
void send(OutputMessage& outputMessage); void send(OutputMessage& outputMessage);
void recv(); void recv();
void internalRecvHeader(uint8* buffer, uint16 size); void internalRecvHeader(uint8* buffer, uint16 size);
void internalRecvData(uint8* buffer, uint16 size); void internalRecvData(uint8* buffer, uint16 size);
virtual void onConnect() = 0; virtual void onConnect() = 0;
virtual void onRecv(InputMessage& inputMessage) = 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<Protocol>(shared_from_this()); } ProtocolPtr asProtocol() { return std::static_pointer_cast<Protocol>(shared_from_this()); }

View File

@ -26,4 +26,11 @@ enum ThingType {
THING_SHOT THING_SHOT
}; };
enum Direction {
DIRECTION_NORTH,
DIRECTION_EAST,
DIRECTION_SOUTH,
DIRECTION_WEST
};
#endif #endif

View File

@ -13,10 +13,10 @@ public:
void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes); void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes);
void parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt); void parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt);
const ThingAttributes& getItemAttributes(uint16 id) { return m_itemsAttributes[id - 100]; } ThingAttributes& getItemAttributes(uint16 id) { return m_itemsAttributes[id - 100]; }
const ThingAttributes& getCreatureAttributes(uint16 id) { return m_creaturesAttributes[id - 1]; } ThingAttributes& getCreatureAttributes(uint16 id) { return m_creaturesAttributes[id - 1]; }
const ThingAttributes& getEffectAttributes(uint16 id) { return m_effectsAttributes[id - 100]; } ThingAttributes& getEffectAttributes(uint16 id) { return m_effectsAttributes[id - 100]; }
const ThingAttributes& getShotAttributes(uint16 id) { return m_shotsAttributes[id - 1]; } ThingAttributes& getShotAttributes(uint16 id) { return m_shotsAttributes[id - 1]; }
uint32 getSignature() { return m_signature; } uint32 getSignature() { return m_signature; }

View File

@ -1,13 +1,32 @@
#include "game.h" #include "game.h"
#include "localplayer.h" #include "localplayer.h"
#include <otclient/net/protocolgame.h>
Game g_game; Game g_game;
Game::Game() void Game::init()
{ {
m_online = false; 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() void Game::onLogin()
{ {
m_localPlayer = LocalPlayerPtr(new LocalPlayer); m_localPlayer = LocalPlayerPtr(new LocalPlayer);
@ -16,6 +35,7 @@ void Game::onLogin()
void Game::onLogout() void Game::onLogout()
{ {
m_protocolGame.reset();
m_localPlayer.reset(); m_localPlayer.reset();
m_online = false; m_online = false;
} }

View File

@ -7,17 +7,22 @@
class Game class Game
{ {
public: 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 onLogin();
void onLogout(); void onLogout();
void setProtocol(ProtocolGamePtr protocolGame) { m_protocolGame = protocolGame; }
bool isOnline() { return m_online; } bool isOnline() { return m_online; }
ProtocolGamePtr getProtocol() { return m_protocolGame; }
LocalPlayerPtr getLocalPlayer() { return m_localPlayer; } LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
private: private:
LocalPlayerPtr m_localPlayer; LocalPlayerPtr m_localPlayer;

View File

@ -11,7 +11,7 @@ public:
void draw(int x, int y); 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; } int getCount() { return m_count; }
const ThingAttributes& getAttributes(); const ThingAttributes& getAttributes();
@ -19,7 +19,7 @@ public:
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); } ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
private: private:
uint8 m_count; int m_count;
}; };
#endif #endif

View File

@ -5,12 +5,6 @@
#include "effect.h" #include "effect.h"
#include <framework/graphics/declarations.h> #include <framework/graphics/declarations.h>
struct MapPositionHasher : std::unary_function<Position, std::size_t> {
std::size_t operator()(const Position& pos) const {
return ((((pos.x * 65536) + pos.y) * 15) + pos.z) % 1000000;
}
};
class Map class Map
{ {
public: public:
@ -19,7 +13,7 @@ public:
void draw(int x, int y); void draw(int x, int y);
private: private:
std::unordered_map<Position, TilePtr, MapPositionHasher> m_tiles; std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;
std::list<ThingPtr> m_effects; std::list<ThingPtr> m_effects;
FrameBufferPtr m_framebuffer; FrameBufferPtr m_framebuffer;

View File

@ -2,6 +2,10 @@
#include "spritemanager.h" #include "spritemanager.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
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) void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim)
{ {
const ThingAttributes& attributes = getAttributes(); const ThingAttributes& attributes = getAttributes();

View File

@ -8,7 +8,7 @@
class Thing : public LuaObject class Thing : public LuaObject
{ {
public: public:
Thing(ThingType type) : m_id(0), m_type(type) { } Thing(ThingType type);
virtual ~Thing() { } virtual ~Thing() { }
virtual void draw(int x, int y) = 0; virtual void draw(int x, int y) = 0;

View File

@ -19,7 +19,7 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos)
if(thingAttributes.alwaysOnTop) if(thingAttributes.alwaysOnTop)
m_itemsTop.push_back(thing); m_itemsTop.push_back(thing);
else else
m_itemsBot.push_back(thing); m_itemsBottom.push_back(thing);
} }
} else if(thing->asCreature()) { } else if(thing->asCreature()) {
m_creatures.push_back(thing); m_creatures.push_back(thing);
@ -31,7 +31,7 @@ void Tile::draw(int x, int y)
if(m_ground) if(m_ground)
m_ground->draw(x, y); m_ground->draw(x, y);
for(const ThingPtr& thing : m_itemsBot) for(const ThingPtr& thing : m_itemsBottom)
thing->draw(x, y); thing->draw(x, y);
for(const ThingPtr& thing : m_creatures) for(const ThingPtr& thing : m_creatures)
@ -46,7 +46,7 @@ int Tile::getStackSize()
int ret = 0; int ret = 0;
if(m_ground) if(m_ground)
ret++; ret++;
ret += m_itemsBot.size(); ret += m_itemsBottom.size();
ret += m_creatures.size(); ret += m_creatures.size();
ret += m_itemsTop.size(); ret += m_itemsTop.size();
return ret; return ret;

View File

@ -19,7 +19,7 @@ public:
private: private:
ThingPtr m_ground; ThingPtr m_ground;
std::deque<ThingPtr> m_itemsBot; std::deque<ThingPtr> m_itemsBottom;
std::deque<ThingPtr> m_creatures; std::deque<ThingPtr> m_creatures;
std::deque<ThingPtr> m_itemsTop; std::deque<ThingPtr> m_itemsTop;
}; };

View File

@ -1,17 +1,10 @@
#include <otclient/net/protocolgame.h> #include <otclient/net/protocolgame.h>
#include <otclient/core/game.h> #include <otclient/core/game.h>
#include <framework/net/rsa.h>
ProtocolGame::ProtocolGame() ProtocolGame::ProtocolGame()
{ {
m_checksumEnabled = false; m_checksumEnabled = false;
g_game.setProtocol(ProtocolGamePtr(this)); m_waitingLoginPacket = false;
}
ProtocolGame::~ProtocolGame()
{
sendLogout();
g_game.setProtocol(NULL);
} }
void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName) 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; return;
} }
m_waitingLoginPacket = true;
m_accountName = accountName; m_accountName = accountName;
m_accountPassword = accountPassword; m_accountPassword = accountPassword;
m_characterName = characterName; m_characterName = characterName;
@ -36,64 +30,27 @@ void ProtocolGame::onConnect()
recv(); 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) void ProtocolGame::onRecv(InputMessage& inputMessage)
{ {
static bool firstRecv = true; if(m_waitingLoginPacket) {
if(firstRecv) {
inputMessage.skipBytes(3); inputMessage.skipBytes(3);
uint32 timestamp = inputMessage.getU32(); uint32 timestamp = inputMessage.getU32();
uint8 unknown = inputMessage.getU8(); uint8 unknown = inputMessage.getU8();
m_waitingLoginPacket = false;
m_checksumEnabled = true; m_checksumEnabled = true;
sendLoginPacket(timestamp, unknown); sendLoginPacket(timestamp, unknown);
recv();
firstRecv = false;
} }
else { else {
parseMessage(inputMessage); parseMessage(inputMessage);
recv();
} }
} }
void ProtocolGame::onError(const boost::system::error_code& error)
{
// already disconnected, just send onLogout
g_game.onLogout();
}

View File

@ -9,16 +9,15 @@
class ProtocolGame : public Protocol class ProtocolGame : public Protocol
{ {
public: public:
ProtocolGame(); ProtocolGame();
~ProtocolGame();
public: public:
void login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName); void login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName);
void onConnect(); void onConnect();
void onRecv(InputMessage& inputMessage); void onRecv(InputMessage& inputMessage);
void onError(const boost::system::error_code& error);
void sendLogout(); void sendLogout();
void sendPing(); void sendPing();
@ -115,6 +114,7 @@ private:
Position parsePosition(InputMessage& msg); Position parsePosition(InputMessage& msg);
private: private:
bool m_waitingLoginPacket;
std::string m_accountName; std::string m_accountName;
std::string m_accountPassword; std::string m_accountPassword;
std::string m_characterName; std::string m_characterName;

View File

@ -226,7 +226,6 @@ void ProtocolGame::parseMessage(InputMessage& msg)
break; break;
} }
} }
recv();
} }
void ProtocolGame::parsePlayerLogin(InputMessage& msg) void ProtocolGame::parsePlayerLogin(InputMessage& msg)
@ -629,7 +628,6 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
msg.getU32(); // time msg.getU32(); // time
break; break;
default: default:
//qDebug() << "Unknown speak type. opt: 0xAA, type: " << type;
break; break;
} }
@ -691,7 +689,7 @@ void ProtocolGame::parseTextMessage(InputMessage& msg)
{ {
msg.getU8(); // messageType msg.getU8(); // messageType
std::string message = msg.getString(); std::string message = msg.getString();
logDebug(message); //logDebug(message);
} }
void ProtocolGame::parseCancelWalk(InputMessage& msg) void ProtocolGame::parseCancelWalk(InputMessage& msg)
@ -813,8 +811,6 @@ void ProtocolGame::setMapDescription(InputMessage& msg, int32 x, int32 y, int32
zstep = -1; zstep = -1;
} }
logDebug((int)startz);
for(int nz = startz; nz != endz + zstep; nz += zstep) for(int nz = startz; nz != endz + zstep; nz += zstep)
setFloorDescription(msg, x, y, nz, width, height, z - nz, &skip); setFloorDescription(msg, x, y, nz, width, height, z - nz, &skip);
} }

View File

@ -1,4 +1,47 @@
#include "protocolgame.h" #include "protocolgame.h"
#include <framework/net/rsa.h>
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() void ProtocolGame::sendLogout()
{ {

View File

@ -6,15 +6,10 @@
// TODO just testing // TODO just testing
#include "protocolgame.h" #include "protocolgame.h"
#include <otclient/core/game.h>
ProtocolLogin::ProtocolLogin() ProtocolLogin::ProtocolLogin()
{ {
}
ProtocolLogin::~ProtocolLogin()
{
} }
void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword) void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword)
@ -99,7 +94,6 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage)
{ {
while(!inputMessage.end()) { while(!inputMessage.end()) {
uint8 opt = inputMessage.getU8(); uint8 opt = inputMessage.getU8();
logDebug("opt:",(uint)opt);
switch(opt) { switch(opt) {
case 0x0A: case 0x0A:
parseError(inputMessage); 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) void ProtocolLogin::parseError(InputMessage& inputMessage)
{ {
std::string error = inputMessage.getString(); std::string error = inputMessage.getString();
logDebug(error);
callLuaField("onError", error); callLuaField("onError", error);
disconnect();
} }
void ProtocolLogin::parseMOTD(InputMessage& inputMessage) void ProtocolLogin::parseMOTD(InputMessage& inputMessage)
{ {
std::string motd = inputMessage.getString(); std::string motd = inputMessage.getString();
logDebug(motd);
callLuaField("onMotd", motd); callLuaField("onMotd", motd);
} }
@ -140,14 +139,12 @@ void ProtocolLogin::parseCharacterList(InputMessage& inputMessage)
uint32 ip = inputMessage.getU32(); uint32 ip = inputMessage.getU32();
uint16 port = inputMessage.getU16(); uint16 port = inputMessage.getU16();
logDebug("character: ", name.c_str(), world.c_str(), ip, " ", port);
// TODO just test // TODO just test
if(i == 0) { if(i == 0) {
ProtocolGamePtr protocolGame = ProtocolGamePtr(new ProtocolGame); g_game.loginWorld(m_accountName, m_accountPassword, ip, port, name);
protocolGame->login(m_accountName, m_accountPassword, ip, port, name); break;
} }
} }
uint16 premiumDays = inputMessage.getU16(); /*uint16 premiumDays =*/ inputMessage.getU16();
logDebug("prem days: ", premiumDays); disconnect();
} }

View File

@ -11,7 +11,6 @@ class ProtocolLogin : public Protocol
{ {
public: public:
ProtocolLogin(); ProtocolLogin();
~ProtocolLogin();
static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); } static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); }
@ -19,6 +18,7 @@ public:
void onConnect(); void onConnect();
void onRecv(InputMessage& inputMessage); void onRecv(InputMessage& inputMessage);
void onError(const boost::system::error_code& error);
void cancel() { /* TODO: this func */ } void cancel() { /* TODO: this func */ }

View File

@ -62,6 +62,8 @@ void OTClient::init(std::vector<std::string> args)
// initialize the ui // initialize the ui
g_ui.init(); g_ui.init();
g_game.init();
// discover and load modules // discover and load modules
g_modules.discoverAndLoadModules(); g_modules.discoverAndLoadModules();
@ -146,6 +148,8 @@ void OTClient::terminate()
// run modules unload event // run modules unload event
g_modules.unloadModules(); g_modules.unloadModules();
g_game.terminate();
// terminate ui // terminate ui
g_ui.terminate(); g_ui.terminate();
@ -156,6 +160,7 @@ void OTClient::terminate()
poll(); poll();
// terminate network // terminate network
Connection::terminate();
//g_network.terminate(); //g_network.terminate();
// terminate dispatcher // terminate dispatcher
@ -263,7 +268,7 @@ void OTClient::onPlatformEvent(const PlatformEvent& event)
{ {
g_ui.inputEvent(event); g_ui.inputEvent(event);
ProtocolGamePtr protocol = g_game.getProtocol(); ProtocolGamePtr protocol = g_game.getProtocolGame();
if(protocol) { if(protocol) {
if(event.type == EventKeyDown) { if(event.type == EventKeyDown) {
if(event.keycode == KC_UP) if(event.keycode == KC_UP)

View File

@ -8,9 +8,6 @@
void OTClient::registerLuaFunctions() void OTClient::registerLuaFunctions()
{ {
// easy typing _1, _2, ...
using namespace std::placeholders;
g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client)); g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client));
g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1)); g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1));
g_lua.bindGlobalFunction("importDat", std::bind(&DatManager::load, &g_dat, _1)); g_lua.bindGlobalFunction("importDat", std::bind(&DatManager::load, &g_dat, _1));

View File

@ -3,14 +3,6 @@
#include <framework/util/types.h> #include <framework/util/types.h>
enum Direction
{
DIRECTION_NORTH,
DIRECTION_EAST,
DIRECTION_SOUTH,
DIRECTION_WEST
};
class Position class Position
{ {
public: public:
@ -33,6 +25,12 @@ public:
int z; int z;
}; };
struct PositionHasher : std::unary_function<Position, std::size_t> {
std::size_t operator()(const Position& pos) const {
return ((((pos.x * 65536) + pos.y) * 15) + pos.z) % 1000000;
}
};
template<class T> template<class T>
std::ostream& operator<<(std::ostream& out, const Position& pos) std::ostream& operator<<(std::ostream& out, const Position& pos)
{ {