Improve walk when lagging

This commit is contained in:
Eduardo Bart 2013-03-13 20:55:20 -03:00
parent 0891e2b30a
commit e9e4dcd71b
9 changed files with 79 additions and 29 deletions

View File

@ -104,8 +104,8 @@ function bindKeys()
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel) g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel) g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel) g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+Q', tryLogout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+L', tryLogout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
end end
@ -215,8 +215,8 @@ function tryExit()
return true return true
end end
local exitFunc = function() logout() forceExit() end local exitFunc = function() g_game.safeLogout() forceExit() end
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."), exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
@ -228,13 +228,6 @@ function tryExit()
return true return true
end end
function logout()
if g_game.isOnline() then
g_game.safeLogout()
return true
end
end
function tryLogout() function tryLogout()
if not g_game.isOnline() then if not g_game.isOnline() then
exit() exit()
@ -245,14 +238,34 @@ function tryLogout()
return return
end end
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end if not g_game.isConnectionOk() then
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end local yesCallback = function()
g_game.forceLogout()
logoutWindow=nil
end
local noCallback = function()
logoutWindow=nil
end
logoutWindow = displayGeneralBox(tr('Logout'), tr('Your connection is failing, if you logout now your character will be still online, do you want to force logout?'), {
{ text=tr('Yes'), callback=yesCallback },
{ text=tr('No'), callback=noCallback },
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
else
local yesCallback = function()
g_game.safeLogout()
logoutWindow=nil
end
local noCallback = function()
logoutWindow=nil
end
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), { logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
{ text=tr('Yes'), callback=yesCallback }, { text=tr('Yes'), callback=yesCallback },
{ text=tr('No'), callback=noCallback }, { text=tr('No'), callback=noCallback },
anchor=AnchorHorizontalCenter}, yesCallback, noCallback) anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
end end
end
function stopSmartWalk() function stopSmartWalk()
smartWalkDirs = {} smartWalkDirs = {}

View File

@ -99,6 +99,11 @@ void Game::resetGameStates()
m_walkEvent = nullptr; m_walkEvent = nullptr;
} }
if(m_checkConnectionEvent) {
m_checkConnectionEvent->cancel();
m_checkConnectionEvent = nullptr;
}
m_containers.clear(); m_containers.clear();
m_vips.clear(); m_vips.clear();
m_gmActions.clear(); m_gmActions.clear();
@ -183,6 +188,16 @@ void Game::processGameStart()
g_game.ping(); g_game.ping();
}, m_pingDelay); }, m_pingDelay);
} }
m_checkConnectionEvent = g_dispatcher.cycleEvent([this] {
if(!g_game.isConnectionOk() && !m_connectionFailWarned) {
g_lua.callGlobalField("g_game", "onConnectionFailing", true);
m_connectionFailWarned = true;
} else if(g_game.isConnectionOk() && m_connectionFailWarned) {
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
m_connectionFailWarned = false;
}
}, 1000);
} }
void Game::processGameEnd() void Game::processGameEnd()
@ -190,6 +205,11 @@ void Game::processGameEnd()
m_online = false; m_online = false;
g_lua.callGlobalField("g_game", "onGameEnd"); g_lua.callGlobalField("g_game", "onGameEnd");
if(m_connectionFailWarned) {
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
m_connectionFailWarned = false;
}
// reset game state // reset game state
resetGameStates(); resetGameStates();
@ -551,6 +571,7 @@ bool Game::walk(Otc::Direction direction)
// check we can walk and add new walk event if false // check we can walk and add new walk event if false
if(!m_localPlayer->canWalk(direction)) { if(!m_localPlayer->canWalk(direction)) {
/*
if(m_lastWalkDir != direction) { if(m_lastWalkDir != direction) {
// must add a new walk event // must add a new walk event
float ticks = m_localPlayer->getStepTicksLeft(); float ticks = m_localPlayer->getStepTicksLeft();
@ -562,6 +583,7 @@ bool Game::walk(Otc::Direction direction)
} }
m_walkEvent = g_dispatcher.scheduleEvent([=] { walk(direction); }, ticks); m_walkEvent = g_dispatcher.scheduleEvent([=] { walk(direction); }, ticks);
} }
*/
return false; return false;
} }
@ -697,7 +719,9 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
auto it = dirs.begin(); auto it = dirs.begin();
Otc::Direction direction = *it; Otc::Direction direction = *it;
if(m_localPlayer->canWalk(direction)) { if(!m_localPlayer->canWalk(direction))
return;
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction)); TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) { if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
m_localPlayer->preWalk(direction); m_localPlayer->preWalk(direction);
@ -707,7 +731,6 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
dirs.erase(it); dirs.erase(it);
} }
} }
}
g_lua.callGlobalField("g_game", "onAutoWalk", dirs); g_lua.callGlobalField("g_game", "onAutoWalk", dirs);

View File

@ -281,6 +281,7 @@ public:
bool isDead() { return m_dead; } bool isDead() { return m_dead; }
bool isAttacking() { return !!m_attackingCreature; } bool isAttacking() { return !!m_attackingCreature; }
bool isFollowing() { return !!m_followingCreature; } bool isFollowing() { return !!m_followingCreature; }
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; } int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
ContainerPtr getContainer(int index) { return m_containers[index]; } ContainerPtr getContainer(int index) { return m_containers[index]; }
@ -340,6 +341,8 @@ private:
std::bitset<Otc::LastGameFeature> m_features; std::bitset<Otc::LastGameFeature> m_features;
ScheduledEventPtr m_pingEvent; ScheduledEventPtr m_pingEvent;
ScheduledEventPtr m_walkEvent; ScheduledEventPtr m_walkEvent;
ScheduledEventPtr m_checkConnectionEvent;
bool m_connectionFailWarned;
int m_protocolVersion; int m_protocolVersion;
int m_clientVersion; int m_clientVersion;
std::string m_clientSignature; std::string m_clientSignature;

View File

@ -83,7 +83,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
return false; return false;
// cannot walk while already walking // cannot walk while already walking
if(m_walking && !prewalkTimeouted) if(m_walking && (!prewalkTimeouted || m_secondPreWalk))
return false; return false;
return true; return true;
@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
if(m_preWalking) { if(m_preWalking) {
// switch to normal walking // switch to normal walking
m_preWalking = false; m_preWalking = false;
m_secondPreWalk = false;
m_lastPrewalkDone = true; m_lastPrewalkDone = true;
// if is to the last prewalk destination, updates the walk preserving the animation // if is to the last prewalk destination, updates the walk preserving the animation
if(newPos == m_lastPrewalkDestination) { if(newPos == m_lastPrewalkDestination) {
@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
Position newPos = m_position.translatedToDirection(direction); Position newPos = m_position.translatedToDirection(direction);
// avoid reanimating prewalks // avoid reanimating prewalks
if(m_preWalking && m_lastPrewalkDestination == newPos) { if(m_preWalking) {
m_secondPreWalk = true;
return; return;
} }
@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
{ {
Creature::terminateWalk(); Creature::terminateWalk();
m_preWalking = false; m_preWalking = false;
m_secondPreWalk = false;
m_idleTimer.restart(); m_idleTimer.restart();
auto self = asLocalPlayer(); auto self = asLocalPlayer();

View File

@ -126,6 +126,7 @@ private:
ticks_t m_walkLockExpiration; ticks_t m_walkLockExpiration;
stdext::boolean<false> m_preWalking; stdext::boolean<false> m_preWalking;
stdext::boolean<true> m_lastPrewalkDone; stdext::boolean<true> m_lastPrewalkDone;
stdext::boolean<false> m_secondPreWalk;
stdext::boolean<false> m_serverWalking; stdext::boolean<false> m_serverWalking;
stdext::boolean<false> m_knownCompletePath; stdext::boolean<false> m_knownCompletePath;

View File

@ -230,6 +230,7 @@ void Client::registerLuaFunctions()
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game); g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game); g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game); g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game); g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game); g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game); g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);

View File

@ -125,7 +125,7 @@ void Connection::write(uint8* buffer, size_t size)
m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf); m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf);
m_delayedWriteTimer.cancel(); m_delayedWriteTimer.cancel();
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(1)); m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(10));
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1)); m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
} }
@ -215,6 +215,7 @@ void Connection::onResolve(const boost::system::error_code& error, asio::ip::bas
void Connection::onConnect(const boost::system::error_code& error) void Connection::onConnect(const boost::system::error_code& error)
{ {
m_readTimer.cancel(); m_readTimer.cancel();
m_activityTimer.restart();
if(error == asio::error::operation_aborted) if(error == asio::error::operation_aborted)
return; return;
@ -263,6 +264,7 @@ void Connection::onWrite(const boost::system::error_code& error, size_t writeSiz
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize) void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
{ {
m_readTimer.cancel(); m_readTimer.cancel();
m_activityTimer.restart();
if(error == asio::error::operation_aborted) if(error == asio::error::operation_aborted)
return; return;

View File

@ -61,6 +61,7 @@ public:
boost::system::error_code getError() { return m_error; } boost::system::error_code getError() { return m_error; }
bool isConnecting() { return m_connecting; } bool isConnecting() { return m_connecting; }
bool isConnected() { return m_connected; } bool isConnected() { return m_connected; }
ticks_t getElapsedTicksSinceLastRead() { return m_connected ? m_activityTimer.elapsed_millis() : -1; }
ConnectionPtr asConnection() { return static_self_cast<Connection>(); } ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
@ -91,6 +92,7 @@ protected:
bool m_connected; bool m_connected;
bool m_connecting; bool m_connecting;
boost::system::error_code m_error; boost::system::error_code m_error;
stdext::timer m_activityTimer;
friend class Server; friend class Server;
}; };

View File

@ -42,6 +42,8 @@ public:
bool isConnected(); bool isConnected();
bool isConnecting(); bool isConnecting();
ticks_t getElapsedTicksSinceLastRead() { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
ConnectionPtr getConnection() { return m_connection; } ConnectionPtr getConnection() { return m_connection; }
void setConnection(const ConnectionPtr& connection) { m_connection = connection; } void setConnection(const ConnectionPtr& connection) { m_connection = connection; }