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('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+Q', tryLogout, 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+.', nextViewMode, gameRootPanel)
end
@ -215,8 +215,8 @@ function tryExit()
return true
end
local exitFunc = function() logout() forceExit() end
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
local exitFunc = function() g_game.safeLogout() forceExit() end
local logoutFunc = function() g_game.safeLogout() 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."),
@ -228,13 +228,6 @@ function tryExit()
return true
end
function logout()
if g_game.isOnline() then
g_game.safeLogout()
return true
end
end
function tryLogout()
if not g_game.isOnline() then
exit()
@ -245,13 +238,33 @@ function tryLogout()
return
end
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
if not g_game.isConnectionOk() then
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?'), {
{ text=tr('Yes'), callback=yesCallback },
{ text=tr('No'), callback=noCallback },
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
end
end
function stopSmartWalk()

View File

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

View File

@ -281,6 +281,7 @@ public:
bool isDead() { return m_dead; }
bool isAttacking() { return !!m_attackingCreature; }
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; }
ContainerPtr getContainer(int index) { return m_containers[index]; }
@ -340,6 +341,8 @@ private:
std::bitset<Otc::LastGameFeature> m_features;
ScheduledEventPtr m_pingEvent;
ScheduledEventPtr m_walkEvent;
ScheduledEventPtr m_checkConnectionEvent;
bool m_connectionFailWarned;
int m_protocolVersion;
int m_clientVersion;
std::string m_clientSignature;

View File

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

View File

@ -126,6 +126,7 @@ private:
ticks_t m_walkLockExpiration;
stdext::boolean<false> m_preWalking;
stdext::boolean<true> m_lastPrewalkDone;
stdext::boolean<false> m_secondPreWalk;
stdext::boolean<false> m_serverWalking;
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", "isAttacking", &Game::isAttacking, &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", "getContainer", &Game::getContainer, &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_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));
}
@ -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)
{
m_readTimer.cancel();
m_activityTimer.restart();
if(error == asio::error::operation_aborted)
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)
{
m_readTimer.cancel();
m_activityTimer.restart();
if(error == asio::error::operation_aborted)
return;

View File

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

View File

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