From e85eb879bb8d7d38a05f3b6d0de94d380ef1021c Mon Sep 17 00:00:00 2001 From: lotodore Date: Thu, 6 Mar 2008 20:44:37 +0000 Subject: [PATCH] Game admin timeout in lobby (test version). --- src/net/common/servergamestate.cpp | 53 +++++++++++++++++++++++++++-- src/net/common/servergamethread.cpp | 16 ++++++++- src/net/servergamestate.h | 9 +++-- src/net/servergamethread.h | 3 ++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 1d3a4504..76c5f633 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -62,6 +62,9 @@ using namespace std; #define SERVER_COMPUTER_ACTION_DELAY_SEC 2 #endif +#define SERVER_GAME_ADMIN_WARNING_REMAINING_SEC 60 +#define SERVER_GAME_ADMIN_TIMEOUT_SEC 70 // MUST be > SERVER_GAME_ADMIN_WARNING_REMAINING_SEC + // Helper functions // TODO: these are hacks. @@ -177,8 +180,6 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) // Delegate to Lobby. server.GetLobbyThread().HandleGameRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); } - else if (packet->ToNetPacketResetTimeout()) - {} else if (packet->ToNetPacketLeaveCurrentGame()) { server.MoveSessionToLobby(session, NTF_NET_REMOVED_ON_REQUEST); @@ -234,6 +235,7 @@ AbstractServerGameStateTimer::Init(ServerGameThread & server) // Reset timer. server.GetStateTimer().reset(); server.GetStateTimer().start(); + server.SetStateTimerFlag(0); } //----------------------------------------------------------------------------- @@ -254,6 +256,13 @@ ServerGameStateInit::~ServerGameStateInit() { } +void +ServerGameStateInit::NotifyGameAdminChanged(ServerGameThread &server) +{ + // Reset admin timer. + AbstractServerGameStateTimer::Init(server); +} + void ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper session) { @@ -305,6 +314,38 @@ ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper s } } +int +ServerGameStateInit::Process(ServerGameThread &server) +{ + if (server.GetStateTimer().elapsed().total_seconds() >= SERVER_GAME_ADMIN_TIMEOUT_SEC - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC + && !server.GetStateTimerFlag()) + { + // Admin timeout - notify game admin. + server.SetStateTimerFlag(1); // Only once. + // Find game admin. + SessionWrapper session = server.GetSessionManager().GetSessionByUniquePlayerId(server.GetAdminPlayerId()); + if (session.sessionData.get()) + { + boost::shared_ptr warning(new NetPacketTimeoutWarning); + NetPacketTimeoutWarning::Data warningData; + warningData.timeoutReason = NETWORK_TIMEOUT_GAME_ADMIN_IDLE; + warningData.remainingSeconds = SERVER_GAME_ADMIN_WARNING_REMAINING_SEC; + static_cast(warning.get())->SetData(warningData); + server.GetSender().Send(session.sessionData, warning); + } + } + else if (server.GetStateTimer().elapsed().total_seconds() >= SERVER_GAME_ADMIN_TIMEOUT_SEC) + { + // Find game admin. + SessionWrapper session = server.GetSessionManager().GetSessionByUniquePlayerId(server.GetAdminPlayerId()); + if (session.sessionData.get()) + { + server.RemovePlayer(session.playerData->GetUniqueId(), ERR_NET_PLAYER_KICKED); // TODO use proper error code. + } + } + return AbstractServerGameStateReceiving::Process(server); +} + int ServerGameStateInit::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { @@ -347,6 +388,14 @@ ServerGameStateInit::InternalProcess(ServerGameThread &server, SessionWrapper se server.SetState(ServerGameStateWaitAck::Instance()); } } + else if (packet->ToNetPacketResetTimeout()) + { + if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN) + { + // Reset admin timer. + AbstractServerGameStateTimer::Init(server); + } + } else { server.SessionError(session, ERR_SOCK_INVALID_PACKET); diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index 123f1402..fb7554a4 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -38,7 +38,8 @@ ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id, : m_adminPlayerId(adminPlayerId), m_lobbyThread(lobbyThread), m_gui(gui), m_gameData(gameData), m_id(id), m_name(name), m_password(pwd), m_playerConfig(playerConfig), m_curState(NULL), m_gameNum(1), - m_stateTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start) + m_stateTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::manual_start), + m_stateTimerFlag(0) { m_receiver.reset(new ReceiverHelper); } @@ -350,6 +351,8 @@ ServerGameThread::RemovePlayerData(boost::shared_ptr player) boost::shared_ptr newAdmin = playerList.front(); SetAdminPlayerId(newAdmin->GetUniqueId()); newAdmin->SetRights(PLAYER_RIGHTS_ADMIN); + // Notify game state on admin change + GetState().NotifyGameAdminChanged(*this); // Send "Game Admin Changed" to clients. boost::shared_ptr adminChanged(new NetPacketGameAdminChanged); NetPacketGameAdminChanged::Data adminChangedData; @@ -491,6 +494,17 @@ ServerGameThread::GetStateTimer() return m_stateTimer; } +unsigned +ServerGameThread::GetStateTimerFlag() const +{ + return m_stateTimerFlag; +} +void +ServerGameThread::SetStateTimerFlag(unsigned flag) +{ + m_stateTimerFlag = flag; +} + SenderThread & ServerGameThread::GetSender() { diff --git a/src/net/servergamestate.h b/src/net/servergamestate.h index 6035d108..d9729b90 100644 --- a/src/net/servergamestate.h +++ b/src/net/servergamestate.h @@ -45,6 +45,7 @@ public: // Initialize after switching to this state. virtual void Init(ServerGameThread &server) = 0; + virtual void NotifyGameAdminChanged(ServerGameThread &server) = 0; // Handling of a new session. virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session) = 0; @@ -76,6 +77,8 @@ class AbstractServerGameStateRunning : virtual public ServerGameState public: virtual ~AbstractServerGameStateRunning(); + virtual void NotifyGameAdminChanged(ServerGameThread &/*server*/) {} + // Reject new connections. virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); @@ -94,7 +97,7 @@ public: }; // State: Initialization. -class ServerGameStateInit : public AbstractServerGameStateReceiving +class ServerGameStateInit : public AbstractServerGameStateReceiving, public AbstractServerGameStateTimer { public: // Access the state singleton. @@ -102,8 +105,10 @@ public: virtual ~ServerGameStateInit(); - virtual void Init(ServerGameThread & /*server*/) {} + virtual void NotifyGameAdminChanged(ServerGameThread &server); + // + virtual int Process(ServerGameThread &server); virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); protected: diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index 8f6c07ff..8776da17 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -109,6 +109,8 @@ protected: const boost::timers::portable::microsec_timer &GetStateTimer() const; boost::timers::portable::microsec_timer &GetStateTimer(); + unsigned GetStateTimerFlag() const; + void SetStateTimerFlag(unsigned flag); SenderThread &GetSender(); ReceiverHelper &GetReceiver(); @@ -153,6 +155,7 @@ private: unsigned m_gameNum; boost::timers::portable::microsec_timer m_stateTimer; + unsigned m_stateTimerFlag; friend class AbstractServerGameStateReceiving; friend class AbstractServerGameStateRunning;