From 71931b961a86f06b4557388dbcf81c72dc9723d7 Mon Sep 17 00:00:00 2001 From: TheSumm Date: Tue, 27 Jan 2015 23:44:37 +0100 Subject: [PATCH] Full protocol 10.74 support (session key), entergame style fixes --- modules/client_entergame/characterlist.lua | 2 +- modules/client_entergame/entergame.lua | 95 +++++++++++++++------- modules/client_entergame/entergame.otui | 52 ++++++++++-- modules/gamelib/const.lua | 1 + modules/gamelib/game.lua | 2 +- modules/gamelib/protocollogin.lua | 18 +++- src/client/const.h | 1 + src/client/game.cpp | 12 ++- src/client/game.h | 2 +- src/client/protocolgame.cpp | 3 +- src/client/protocolgame.h | 3 +- src/client/protocolgamesend.cpp | 21 +++-- 12 files changed, 156 insertions(+), 56 deletions(-) diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index eb639559..35e52ce6 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -27,7 +27,7 @@ local function tryLogin(charInfo, tries) CharacterList.hide() - g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken) + g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken, G.sessionKey) loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...')) connect(loadBox, { onCancel = function() diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 49db7853..81ab23cf 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -33,10 +33,17 @@ local function onMotd(protocol, motd) end end +local function onSessionKey(protocol, sessionKey) + G.sessionKey = sessionKey +end + local function onCharacterList(protocol, characters, account, otui) -- Try add server to the server list ServerList.add(G.host, G.port, g_game.getClientVersion()) + -- Save 'Stay logged in' setting + g_settings.set('staylogged', enterGame:getChildById('stayLoggedBox'):isChecked()) + if enterGame:getChildById('rememberPasswordBox'):isChecked() then local account = g_crypt.encrypt(G.account) local password = g_crypt.encrypt(G.password) @@ -109,9 +116,10 @@ function EnterGame.init() local password = g_settings.get('password') local host = g_settings.get('host') local port = g_settings.get('port') + local stayLogged = g_settings.getBoolean('staylogged') local autologin = g_settings.getBoolean('autologin') local clientVersion = g_settings.getInteger('client-version') - if clientVersion == 0 then clientVersion = 1072 end + if clientVersion == 0 then clientVersion = 1074 end if port == nil or port == 0 then port = 7171 end @@ -121,7 +129,7 @@ function EnterGame.init() enterGame:getChildById('serverHostTextEdit'):setText(host) enterGame:getChildById('serverPortTextEdit'):setText(port) enterGame:getChildById('autoLoginBox'):setChecked(autologin) - + enterGame:getChildById('stayLoggedBox'):setChecked(stayLogged) clientBox = enterGame:getChildById('clientComboBox') for _, proto in pairs(g_game.getSupportedClients()) do @@ -130,6 +138,7 @@ function EnterGame.init() clientBox:setCurrentOption(clientVersion) EnterGame.toggleAuthenticatorToken(clientVersion, true) + EnterGame.toggleStayLoggedBox(clientVersion, true) connect(clientBox, { onOptionChange = EnterGame.onClientVersionChange }) enterGame:hide() @@ -227,48 +236,68 @@ function EnterGame.toggleAuthenticatorToken(clientVersion, init) return end + enterGame:getChildById('authenticatorTokenLabel'):setOn(enabled) + enterGame:getChildById('authenticatorTokenTextEdit'):setOn(enabled) + + local newHeight = enterGame:getHeight() + local newY = enterGame:getY() if enabled then - enterGame:getChildById('authenticatorTokenLabel'):setVisible(true) - enterGame:getChildById('authenticatorTokenTextEdit'):setVisible(true) + newY = newY - enterGame.authenticatorHeight + newHeight = newHeight + enterGame.authenticatorHeight + else + newY = newY + enterGame.authenticatorHeight + newHeight = newHeight - enterGame.authenticatorHeight + end - local serverLabel = enterGame:getChildById('serverLabel') - serverLabel:setMarginTop(serverLabel:getMarginTop() + enterGame.authenticatorHeight) + if not init then + enterGame:breakAnchors() + enterGame:setY(newY) + enterGame:bindRectToParent() + end + enterGame:setHeight(newHeight) - if not init then - enterGame:breakAnchors() - enterGame:setY(enterGame:getY() - enterGame.authenticatorHeight) - enterGame:bindRectToParent() - end + enterGame.authenticatorEnabled = enabled +end - enterGame:setHeight(enterGame:getHeight() + enterGame.authenticatorHeight) - else - enterGame:getChildById('authenticatorTokenLabel'):setVisible(false) - enterGame:getChildById('authenticatorTokenTextEdit'):setVisible(false) +function EnterGame.toggleStayLoggedBox(clientVersion, init) + local enabled = (clientVersion >= 1074) + if enabled == enterGame.stayLoggedBoxEnabled then + return + end - local serverLabel = enterGame:getChildById('serverLabel') - serverLabel:setMarginTop(serverLabel:getMarginTop() - enterGame.authenticatorHeight) + enterGame:getChildById('stayLoggedBox'):setOn(enabled) - if not init then - enterGame:breakAnchors() - enterGame:setY(enterGame:getY() + enterGame.authenticatorHeight) - enterGame:bindRectToParent() - end + local newHeight = enterGame:getHeight() + local newY = enterGame:getY() + if enabled then + newY = newY - enterGame.stayLoggedBoxHeight + newHeight = newHeight + enterGame.stayLoggedBoxHeight + else + newY = newY + enterGame.stayLoggedBoxHeight + newHeight = newHeight - enterGame.stayLoggedBoxHeight + end - enterGame:setHeight(enterGame:getHeight() - enterGame.authenticatorHeight) + if not init then + enterGame:breakAnchors() + enterGame:setY(newY) + enterGame:bindRectToParent() end + enterGame:setHeight(newHeight) - enterGame.authenticatorEnabled = enabled + enterGame.stayLoggedBoxEnabled = enabled end function EnterGame.onClientVersionChange(comboBox, text, data) local clientVersion = tonumber(text) EnterGame.toggleAuthenticatorToken(clientVersion) + EnterGame.toggleStayLoggedBox(clientVersion) end function EnterGame.doLogin() G.account = enterGame:getChildById('accountNameTextEdit'):getText() G.password = enterGame:getChildById('accountPasswordTextEdit'):getText() G.authenticatorToken = enterGame:getChildById('authenticatorTokenTextEdit'):getText() + G.stayLogged = enterGame:getChildById('stayLoggedBox'):isChecked() G.host = enterGame:getChildById('serverHostTextEdit'):getText() G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText()) local clientVersion = tonumber(clientBox:getText()) @@ -287,6 +316,7 @@ function EnterGame.doLogin() protocolLogin = ProtocolLogin.create() protocolLogin.onLoginError = onError protocolLogin.onMotd = onMotd + protocolLogin.onSessionKey = onSessionKey protocolLogin.onCharacterList = onCharacterList protocolLogin.onUpdateNeeded = onUpdateNeeded @@ -302,7 +332,7 @@ function EnterGame.doLogin() g_game.chooseRsa(G.host) if modules.game_things.isLoaded() then - protocolLogin:login(G.host, G.port, G.account, G.password, G.authenticatorToken) + protocolLogin:login(G.host, G.port, G.account, G.password, G.authenticatorToken, G.stayLogged) else loadBox:destroy() loadBox = nil @@ -344,13 +374,16 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig portTextEdit:setText(port) portTextEdit:setVisible(false) portTextEdit:setHeight(0) + local authenticatorTokenTextEdit = enterGame:getChildById('authenticatorTokenTextEdit') authenticatorTokenTextEdit:setText('') - authenticatorTokenTextEdit:setVisible(false) - authenticatorTokenTextEdit:setHeight(0) + authenticatorTokenTextEdit:setOn(false) local authenticatorTokenLabel = enterGame:getChildById('authenticatorTokenLabel') - authenticatorTokenLabel:setVisible(false) - authenticatorTokenLabel:setHeight(0) + authenticatorTokenLabel:setOn(false) + + local stayLoggedBox = enterGame:getChildById('stayLoggedBox') + stayLoggedBox:setChecked(false) + stayLoggedBox:setOn(false) clientBox:setCurrentOption(protocol) clientBox:setVisible(false) @@ -372,11 +405,11 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig serverListButton:setWidth(0) local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox') - rememberPasswordBox:setMarginTop(-14) + rememberPasswordBox:setMarginTop(-8) if not windowWidth then windowWidth = 236 end enterGame:setWidth(windowWidth) - if not windowHeight then windowHeight = 200 end + if not windowHeight then windowHeight = 210 end enterGame:setHeight(windowHeight) end diff --git a/modules/client_entergame/entergame.otui b/modules/client_entergame/entergame.otui index debb0ea9..9b6dff1f 100644 --- a/modules/client_entergame/entergame.otui +++ b/modules/client_entergame/entergame.otui @@ -1,6 +1,6 @@ EnterGameWindow < MainWindow !text: tr('Enter Game') - size: 236 274 + size: 236 298 EnterGameButton < Button width: 64 @@ -23,6 +23,8 @@ EnterGameWindow id: enterGame &authenticatorEnabled: false &authenticatorHeight: 44 + &stayLoggedBoxEnabled: false + &stayLoggedBoxHeight: 24 @onEnter: EnterGame.doLogin() MenuLabel @@ -58,24 +60,52 @@ EnterGameWindow anchors.left: prev.left anchors.top: prev.bottom text-auto-resize: true - margin-top: 8 + margin-top: -12 visible: false + $on: + visible: true + margin-top: 8 + TextEdit id: authenticatorTokenTextEdit anchors.left: parent.left anchors.right: parent.right anchors.top: prev.bottom - margin-top: 2 + margin-top: -22 visible: false max-length: 8 + $on: + visible: true + margin-top: 2 + + CheckBox + id: stayLoggedBox + !text: tr('Stay logged during session') + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 6 + margin-top: -16 + visible: false + + $on: + visible: true + margin-top: 8 + + HorizontalSeparator + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 8 + MenuLabel id: serverLabel !text: tr('Server') anchors.left: prev.left anchors.top: prev.bottom - margin-top: -36 + margin-top: 8 text-auto-resize: true ServerListButton @@ -152,16 +182,24 @@ EnterGameWindow anchors.top: prev.bottom margin-top: 2 + HorizontalSeparator + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 6 + EnterGameButton !text: tr('Ok') anchors.right: parent.right - anchors.bottom: parent.bottom + anchors.top: prev.bottom + margin-top: 4 @onClick: EnterGame.doLogin() Label id: serverInfoLabel font: verdana-11px-rounded - anchors.bottom: parent.bottom + anchors.top: prev.top anchors.left: parent.left + margin-top: 5 color: green - text-auto-resize: true + text-auto-resize: true \ No newline at end of file diff --git a/modules/gamelib/const.lua b/modules/gamelib/const.lua index a27b1fa4..4d64f686 100644 --- a/modules/gamelib/const.lua +++ b/modules/gamelib/const.lua @@ -129,6 +129,7 @@ GameContentRevision = 65 GameExperienceBonus = 66 GameAuthenticator = 67 GameUnjustifiedPoints = 68 +GameSessionKey = 69 TextColors = { red = '#f55e5e', --'#c83200' diff --git a/modules/gamelib/game.lua b/modules/gamelib/game.lua index 8cd02bdf..41f09f51 100644 --- a/modules/gamelib/game.lua +++ b/modules/gamelib/game.lua @@ -73,7 +73,7 @@ function g_game.getSupportedClients() 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1070, 1071, 1072, - 1073 + 1073, 1074 } end diff --git a/modules/gamelib/protocollogin.lua b/modules/gamelib/protocollogin.lua index 5d107eca..9b791b78 100644 --- a/modules/gamelib/protocollogin.lua +++ b/modules/gamelib/protocollogin.lua @@ -7,10 +7,11 @@ LoginServerTokenError = 13 LoginServerUpdate = 17 LoginServerMotd = 20 LoginServerUpdateNeeded = 30 +LoginServerSessionKey = 40 LoginServerCharacterList = 100 LoginServerExtendedCharacterList = 101 -function ProtocolLogin:login(host, port, accountName, accountPassword, authenticatorToken) +function ProtocolLogin:login(host, port, accountName, accountPassword, authenticatorToken, stayLogged) if string.len(host) == 0 or port == nil or port == 0 then signalcall(self.onLoginError, self, tr("You must enter a valid server address and port.")) return @@ -19,6 +20,7 @@ function ProtocolLogin:login(host, port, accountName, accountPassword, authentic self.accountName = accountName self.accountPassword = accountPassword self.authenticatorToken = authenticatorToken + self.stayLogged = stayLogged self.connectCallback = self.sendLoginPacket self:connect(host, port) @@ -109,6 +111,10 @@ function ProtocolLogin:sendLoginPacket() msg:addU8(0) msg:addString(self.authenticatorToken) + if g_game.getFeature(GameSessionKey) then + msg:addU8(booleantonumber(self.stayLogged)) + end + paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset) assert(paddingBytes >= 0) for i = 1, paddingBytes do @@ -144,8 +150,11 @@ function ProtocolLogin:onRecv(msg) self:parseMotd(msg) elseif opcode == LoginServerUpdateNeeded then signalcall(self.onLoginError, self, tr("Client needs update.")) + elseif opcode == LoginServerTokenSuccess then + local unknown = msg:getU8() elseif opcode == LoginServerTokenError then -- TODO: prompt for token here + local unknown = msg:getU8() signalcall(self.onLoginError, self, tr("Invalid authentification token.")) elseif opcode == LoginServerCharacterList then self:parseCharacterList(msg) @@ -154,6 +163,8 @@ function ProtocolLogin:onRecv(msg) elseif opcode == LoginServerUpdate then local signature = msg:getString() signalcall(self.onUpdateNeeded, self, signature) + elseif opcode == LoginServerSessionKey then + self:parseSessionKey(msg) else self:parseOpcode(opcode, msg) end @@ -171,6 +182,11 @@ function ProtocolLogin:parseMotd(msg) signalcall(self.onMotd, self, motd) end +function ProtocolLogin:parseSessionKey(msg) + local sessionKey = msg:getString() + signalcall(self.onSessionKey, self, sessionKey) +end + function ProtocolLogin:parseCharacterList(msg) local characters = {} diff --git a/src/client/const.h b/src/client/const.h index 18ffa33b..9ce1dc37 100644 --- a/src/client/const.h +++ b/src/client/const.h @@ -401,6 +401,7 @@ namespace Otc GameExperienceBonus = 66, GameAuthenticator = 67, GameUnjustifiedPoints = 68, + GameSessionKey = 69, LastGameFeature = 101 }; diff --git a/src/client/game.cpp b/src/client/game.cpp index 1cb8d395..37c9dfdb 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -534,7 +534,7 @@ void Game::processWalkCancel(Otc::Direction direction) m_localPlayer->cancelWalk(direction); } -void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken) +void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey) { if(m_protocolGame || isOnline()) stdext::throw_exception("Unable to login into a world while already online or logging."); @@ -549,7 +549,7 @@ void Game::loginWorld(const std::string& account, const std::string& password, c m_localPlayer->setName(characterName); m_protocolGame = ProtocolGamePtr(new ProtocolGame); - m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName, authenticatorToken); + m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName, authenticatorToken, sessionKey); m_characterName = characterName; m_worldName = worldName; } @@ -1456,7 +1456,7 @@ void Game::setProtocolVersion(int version) if(isOnline()) stdext::throw_exception("Unable to change protocol version while online"); - if(version != 0 && (version < 740 || version > 1073)) + if(version != 0 && (version < 740 || version > 1074)) stdext::throw_exception(stdext::format("Protocol version %d not supported", version)); m_protocolVersion = version; @@ -1474,7 +1474,7 @@ void Game::setClientVersion(int version) if(isOnline()) stdext::throw_exception("Unable to change client version while online"); - if(version != 0 && (version < 740 || version > 1073)) + if(version != 0 && (version < 740 || version > 1074)) stdext::throw_exception(stdext::format("Client version %d not supported", version)); m_features.reset(); @@ -1614,6 +1614,10 @@ void Game::setClientVersion(int version) enableFeature(Otc::GameAuthenticator); } + if(version >= 1074) { + enableFeature(Otc::GameSessionKey); + } + m_clientVersion = version; g_lua.callGlobalField("g_game", "onClientVersionChange", version); diff --git a/src/client/game.h b/src/client/game.h index 8d3a6a9b..b707ed53 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -159,7 +159,7 @@ protected: public: // login related - void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken); + void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey); void cancelLogin(); void forceLogout(); void safeLogout(); diff --git a/src/client/protocolgame.cpp b/src/client/protocolgame.cpp index bab30ef1..107102b6 100644 --- a/src/client/protocolgame.cpp +++ b/src/client/protocolgame.cpp @@ -26,11 +26,12 @@ #include "item.h" #include "localplayer.h" -void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken) +void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey) { m_accountName = accountName; m_accountPassword = accountPassword; m_authenticatorToken = authenticatorToken; + m_sessionKey = sessionKey; m_characterName = characterName; connect(host, port); diff --git a/src/client/protocolgame.h b/src/client/protocolgame.h index 6d65e8f9..68490b7c 100644 --- a/src/client/protocolgame.h +++ b/src/client/protocolgame.h @@ -31,7 +31,7 @@ class ProtocolGame : public Protocol { public: - void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken); + void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey); void send(const OutputMessagePtr& outputMessage); void sendExtendedOpcode(uint8 opcode, const std::string& buffer); @@ -248,6 +248,7 @@ private: std::string m_accountName; std::string m_accountPassword; std::string m_authenticatorToken; + std::string m_sessionKey; std::string m_characterName; LocalPlayerPtr m_localPlayer; }; diff --git a/src/client/protocolgamesend.cpp b/src/client/protocolgamesend.cpp index f0e2d167..2f363eba 100644 --- a/src/client/protocolgamesend.cpp +++ b/src/client/protocolgamesend.cpp @@ -79,16 +79,21 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando msg->addU8(0); // is gm set? } - if(g_game.getFeature(Otc::GameAccountNames)) - msg->addString(m_accountName); - else - msg->addU32(stdext::from_string(m_accountName)); + if(g_game.getFeature(Otc::GameSessionKey)) { + msg->addString(m_sessionKey); + msg->addString(m_characterName); + } else { + if(g_game.getFeature(Otc::GameAccountNames)) + msg->addString(m_accountName); + else + msg->addU32(stdext::from_string(m_accountName)); - msg->addString(m_characterName); - msg->addString(m_accountPassword); + msg->addString(m_characterName); + msg->addString(m_accountPassword); - if(g_game.getFeature(Otc::GameAuthenticator)) - msg->addString(m_authenticatorToken); + if(g_game.getFeature(Otc::GameAuthenticator)) + msg->addString(m_authenticatorToken); + } if(g_game.getFeature(Otc::GameChallengeOnLogin)) { msg->addU32(challengeTimestamp);