revise network system

master
Eduardo Bart 13 years ago
parent be15b1820d
commit f87b475f49

@ -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

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

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

@ -1,125 +1,147 @@
#include "connection.h"
#include "networkmanager.h"
#include <framework/core/eventdispatcher.h>
#include <boost/asio.hpp>
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<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_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));
}

@ -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(uint8*, uint16)> RecvCallback;
typedef std::function<void()> 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

@ -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;
}

@ -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<Protocol>(shared_from_this()); }

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

@ -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; }

@ -1,13 +1,32 @@
#include "game.h"
#include "localplayer.h"
#include <otclient/net/protocolgame.h>
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;
}

@ -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;

@ -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<Item>(shared_from_this()); }
private:
uint8 m_count;
int m_count;
};
#endif

@ -5,12 +5,6 @@
#include "effect.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
{
public:
@ -19,7 +13,7 @@ public:
void draw(int x, int y);
private:
std::unordered_map<Position, TilePtr, MapPositionHasher> m_tiles;
std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;
std::list<ThingPtr> m_effects;
FrameBufferPtr m_framebuffer;

@ -2,6 +2,10 @@
#include "spritemanager.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)
{
const ThingAttributes& attributes = getAttributes();

@ -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;

@ -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;

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

@ -1,17 +1,10 @@
#include <otclient/net/protocolgame.h>
#include <otclient/core/game.h>
#include <framework/net/rsa.h>
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();
}

@ -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;

@ -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);
}

@ -1,4 +1,47 @@
#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()
{

@ -6,15 +6,10 @@
// TODO just testing
#include "protocolgame.h"
#include <otclient/core/game.h>
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();
}

@ -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 */ }

@ -62,6 +62,8 @@ void OTClient::init(std::vector<std::string> 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)

@ -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));

@ -3,14 +3,6 @@
#include <framework/util/types.h>
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<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>
std::ostream& operator<<(std::ostream& out, const Position& pos)
{

Loading…
Cancel
Save