login/logout/ctrl+g working correctly

This commit is contained in:
Eduardo Bart 2011-08-29 15:38:01 -03:00
parent 8b2cb410c2
commit f41fd0576c
12 changed files with 131 additions and 36 deletions

View File

@ -1,3 +1,6 @@
-- private variables
local showCharacterListOnLogout = true
-- private functions
local function onGameKeyPress(self, keyCode, keyChar, keyboardModifiers)
if keyboardModifiers == KeyboardCtrlModifier then
@ -22,14 +25,28 @@ local function destroyMainInterface()
end
end
-- public functions
function Game.onLogin()
MainMenu.hide()
CharacterList.destroyLoadBox()
createMainInterface()
end
function Game.onConnectionError(message)
CharacterList.destroyLoadBox()
local errorBox = displayErrorBox("Login Error", "Connection error: " .. message)
errorBox.onOk = CharacterList.show
showCharacterListOnLogout = false
end
function Game.onLogout()
MainMenu.show()
CharacterList.show()
if showCharacterListOnLogout then
CharacterList.show()
else
showCharacterListOnLogout = true
end
destroyMainInterface()
end

View File

@ -17,6 +17,27 @@ local function onCharactersWindowKeyPress(self, keyCode, keyChar, keyboardModifi
return false
end
local function tryLogin(charInfo)
CharacterList.hide()
if Game.isOnline() then
Game.logout()
scheduleEvent(function() tryLogin(charInfo) end, 250)
return
end
Game.loginWorld(EnterGame.account, EnterGame.password, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
loadBox = displayCancelBox('Please wait', 'Connecting to game server...')
function loadBox.onCancel()
Game.cancelLogin()
CharacterList.show()
end
-- save last used character
Configs.set('lastUsedCharacter', charInfo.characterName)
end
-- public functions
function CharacterList.create(characters, premDays)
if charactersWindow then
@ -65,21 +86,10 @@ end
function CharacterList.doLogin()
local selected = charactersWindow:getChildById('characterList'):getFocusedChild()
if selected then
--if Game.isOnline() then
-- Game.logout()
--end
Game.loginWorld(EnterGame.account, EnterGame.password, selected.worldHost, selected.worldPort, selected.characterName)
CharacterList.hide()
loadBox = displayCancelBox('Please wait', 'Connecting to game server...')
function loadBox.onCancel()
Game.logout()
CharacterList.show()
end
-- save last used character
Configs.set('lastUsedCharacter', selected.characterName)
local charInfo = { worldHost = selected.worldHost,
worldPort = selected.worldPort,
characterName = selected.characterName }
tryLogin(charInfo)
else
displayErrorBox('Error', 'You must select a character to login!')
end

View File

@ -34,6 +34,7 @@ Connection::Connection() :
m_socket(g_ioService)
{
m_connected = false;
m_connecting = false;
}
void Connection::poll()
@ -50,6 +51,7 @@ void Connection::terminate()
void Connection::connect(const std::string& host, uint16 port, const SimpleCallback& connectCallback)
{
m_connected = false;
m_connecting = true;
m_connectCallback = connectCallback;
asio::ip::tcp::resolver::query query(host, Fw::unsafeCast<std::string>(port));
@ -61,22 +63,23 @@ void Connection::connect(const std::string& host, uint16 port, const SimpleCallb
void Connection::close()
{
if(!m_connected)
if(!m_connected && !m_connecting)
return;
m_connecting = false;
m_connected = false;
m_connectCallback = nullptr;
m_errorCallback = nullptr;
m_recvCallback = nullptr;
m_readTimer.cancel();
m_writeTimer.cancel();
if(m_socket.is_open()) {
m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
boost::system::error_code ec;
m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
m_socket.close();
}
m_connectCallback = nullptr;
m_errorCallback = nullptr;
m_recvCallback = nullptr;
}
void Connection::write(uint8* buffer, uint16 size)
@ -129,9 +132,10 @@ void Connection::onConnect(const boost::system::error_code& error)
{
m_readTimer.cancel();
m_connected = true;
m_connecting = false;
if(!error) {
m_connected = true;
if(m_connectCallback)
g_dispatcher.addEvent(m_connectCallback);
} else
@ -174,7 +178,7 @@ void Connection::handleError(const boost::system::error_code& error)
if(error != asio::error::operation_aborted) {
if(m_errorCallback)
g_dispatcher.addEvent(std::bind(m_errorCallback, error));
if(m_connected)
if(m_connected || m_connecting)
close();
}
}

View File

@ -51,6 +51,7 @@ public:
void setErrorCallback(const ErrorCallback& errorCallback) { m_errorCallback = errorCallback; }
bool isConnecting() const { return m_connecting; }
bool isConnected() const { return m_connected; }
private:
@ -73,6 +74,7 @@ private:
uint8 m_recvBuffer[65538];
uint16 m_recvSize;
bool m_connected;
bool m_connecting;
};
#endif

View File

@ -44,6 +44,20 @@ void Protocol::disconnect()
}
}
bool Protocol::isConnected()
{
if(m_connection && m_connection->isConnected())
return true;
return false;
}
bool Protocol::isConnecting()
{
if(m_connection && m_connection->isConnecting())
return true;
return false;
}
void Protocol::send(OutputMessage& outputMessage)
{
// encrypt

View File

@ -37,6 +37,9 @@ public:
void connect(const std::string& host, uint16 port);
void disconnect();
bool isConnected();
bool isConnecting();
void send(OutputMessage& outputMessage);
void recv();

View File

@ -374,8 +374,7 @@ void UIWidget::insertChild(int index, const UIWidgetPtr& child)
void UIWidget::removeChild(const UIWidgetPtr& child)
{
// remove from children list
auto it = std::find(m_children.begin(), m_children.end(), child);
if(it != m_children.end()) {
if(hasChild(child)) {
// defocus if needed
bool focusAnother = false;
if(m_focusedChild == child) {
@ -383,9 +382,10 @@ void UIWidget::removeChild(const UIWidgetPtr& child)
focusAnother = true;
}
// unlock child if it was locked
unlockChild(child);
if(isChildLocked(child))
unlockChild(child);
auto it = std::find(m_children.begin(), m_children.end(), child);
m_children.erase(it);
// reset child parent
@ -397,7 +397,7 @@ void UIWidget::removeChild(const UIWidgetPtr& child)
// update child states
child->updateStates();
if(focusAnother)
if(focusAnother && !m_focusedChild)
focusPreviousChild(Fw::ActiveFocusReason);
} else
logError("attempt to remove an unknown child from a UIWidget");
@ -474,7 +474,8 @@ void UIWidget::lockChild(const UIWidgetPtr& child)
assert(hasChild(child));
// prevent double locks
unlockChild(child);
if(isChildLocked(child))
unlockChild(child);
// disable all other children
for(const UIWidgetPtr& otherChild : m_children) {
@ -488,7 +489,7 @@ void UIWidget::lockChild(const UIWidgetPtr& child)
// lock child focus
if(child->isFocusable())
focusChild(child, Fw::ActiveFocusReason);
focusChild(child, Fw::ActiveFocusReason);
moveChildToTop(child);
}
@ -506,10 +507,12 @@ void UIWidget::unlockChild(const UIWidgetPtr& child)
m_lockedChildren.erase(it);
// find new chick to lock
// find new child to lock
UIWidgetPtr lockedChild;
if(m_lockedChildren.size() > 0)
if(m_lockedChildren.size() > 0) {
lockedChild = m_lockedChildren.front();
assert(hasChild(lockedChild));
}
for(const UIWidgetPtr& otherChild : m_children) {
// lock new child
@ -523,6 +526,19 @@ void UIWidget::unlockChild(const UIWidgetPtr& child)
else
otherChild->setEnabled(true);
}
if(lockedChild) {
if(lockedChild->isFocusable())
focusChild(lockedChild, Fw::ActiveFocusReason);
moveChildToTop(lockedChild);
}
}
bool UIWidget::isChildLocked(const UIWidgetPtr& child)
{
auto it = std::find(m_lockedChildren.begin(), m_lockedChildren.end(), child);
return it != m_lockedChildren.end();
}
void UIWidget::updateParentLayout()

View File

@ -135,6 +135,7 @@ public:
void moveChildToTop(const UIWidgetPtr& child);
void lockChild(const UIWidgetPtr& child);
void unlockChild(const UIWidgetPtr& child);
bool isChildLocked(const UIWidgetPtr& child);
void updateParentLayout();
void updateLayout();

View File

@ -43,26 +43,52 @@ void Game::loginWorld(const std::string& account, const std::string& password, c
m_protocolGame->login(account, password, worldHost, (uint16)worldPort, characterName);
}
void Game::cancelLogin()
{
if(m_protocolGame->isConnected()) {
logout();
} else if(m_protocolGame->isConnecting()) {
m_protocolGame->disconnect();
m_protocolGame.reset();
}
}
void Game::logout()
{
m_protocolGame->sendLogout();
processLogout();
}
void Game::processConnectionError(const boost::system::error_code& error)
{
// connection errors only have meaning if we still have a protocol
if(m_protocolGame) {
g_lua.callGlobalField("Game", "onConnectionError", error.message());
if(m_online)
processLogout();
// disconnect isn't needed, we are already disconnected
m_protocolGame.reset();
}
}
void Game::processLogin(const LocalPlayerPtr& localPlayer)
{
m_localPlayer = localPlayer;
m_online = true;
g_lua.callGlobalField("Game", "onLogin", m_localPlayer);
}
void Game::processLogout()
{
g_lua.callGlobalField("Game", "onLogout", m_localPlayer);
if(m_protocolGame) {
m_protocolGame->disconnect();
m_protocolGame.reset();
}
m_localPlayer.reset();
m_online = false;
}

View File

@ -39,6 +39,7 @@ public:
void cancelLogin();
void logout();
void processConnectionError(const boost::system::error_code& error);
void processLogin(const LocalPlayerPtr& localPlayer);
void processLogout();

View File

@ -70,7 +70,6 @@ void ProtocolGame::onRecv(InputMessage& inputMessage)
void ProtocolGame::onError(const boost::system::error_code& error)
{
// already disconnected, just fire onLogout
g_game.processLogout();
g_game.processConnectionError(error);
}

View File

@ -61,6 +61,8 @@ void OTClient::registerLuaFunctions()
g_lua.registerClass<Game>();
g_lua.bindClassStaticFunction<Game>("loginWorld", std::bind(&Game::loginWorld, &g_game, _1, _2, _3, _4, _5));
g_lua.bindClassStaticFunction<Game>("logout", std::bind(&Game::logout, &g_game));
g_lua.bindClassStaticFunction<Game>("cancelLogin", std::bind(&Game::cancelLogin, &g_game));
g_lua.bindClassStaticFunction<Game>("isOnline", std::bind(&Game::isOnline, &g_game));
g_lua.registerClass<UIMap, UIWidget>();
g_lua.bindClassStaticFunction<UIMap>("create", &UIWidget::create<UIMap>);