Merge pull request #1623 from p-mcgowan/issue_1253
Prevent multiple logins with same username, unless allowed in settings
This commit is contained in:
commit
32bce44f1f
@ -1778,6 +1778,43 @@ void cClientHandle::HandleKeepAlive(int a_KeepAliveID)
|
||||
|
||||
|
||||
|
||||
bool cClientHandle::CheckMultiLogin(const AString & a_Username)
|
||||
{
|
||||
// If the multilogin is allowed, skip this check entirely:
|
||||
if ((cRoot::Get()->GetServer()->DoesAllowMultiLogin()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the player is waiting to be transferred to the World.
|
||||
if (cRoot::Get()->GetServer()->IsPlayerInQueue(a_Username))
|
||||
{
|
||||
Kick("A player of the username is already logged in");
|
||||
return false;
|
||||
}
|
||||
|
||||
class cCallback :
|
||||
public cPlayerListCallback
|
||||
{
|
||||
virtual bool Item(cPlayer * a_Player) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} Callback;
|
||||
|
||||
// Check if the player is in any World.
|
||||
if (cRoot::Get()->DoWithPlayer(a_Username, Callback))
|
||||
{
|
||||
Kick("A player of the username is already logged in");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cClientHandle::HandleHandshake(const AString & a_Username)
|
||||
{
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookHandshake(*this, a_Username))
|
||||
@ -1788,7 +1825,8 @@ bool cClientHandle::HandleHandshake(const AString & a_Username)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
return CheckMultiLogin(a_Username);
|
||||
}
|
||||
|
||||
|
||||
|
@ -280,6 +280,10 @@ public:
|
||||
void HandleEntityLeaveBed (int a_EntityID);
|
||||
void HandleEntitySprinting (int a_EntityID, bool a_IsSprinting);
|
||||
|
||||
/** Kicks the current player if the same username is already logged in.
|
||||
Returns false if a player has been kicked, true otherwise. */
|
||||
bool CheckMultiLogin(const AString & a_Username);
|
||||
|
||||
/** Called when the protocol handshake has been received (for protocol versions that support it;
|
||||
otherwise the first instant when a username is received).
|
||||
Returns true if the player is to be let in, false if they were disconnected
|
||||
|
16
src/Root.cpp
16
src/Root.cpp
@ -643,6 +643,22 @@ bool cRoot::DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback
|
||||
|
||||
|
||||
|
||||
bool cRoot::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback)
|
||||
{
|
||||
for (auto World : m_WorldsByName)
|
||||
{
|
||||
if (World.second->DoWithPlayer(a_PlayerName, a_Callback))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cRoot::GetProtocolVersionTextFromInt(int a_ProtocolVersion)
|
||||
{
|
||||
return cProtocolRecognizer::GetVersionTextFromInt(a_ProtocolVersion);
|
||||
|
@ -129,7 +129,10 @@ public:
|
||||
|
||||
/** Finds the player over his uuid and calls the callback */
|
||||
bool DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
|
||||
|
||||
|
||||
/** Finds the player using it's complete username and calls the callback */
|
||||
bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback);
|
||||
|
||||
// tolua_begin
|
||||
|
||||
/// Sends a chat message to all connected clients (in all worlds)
|
||||
|
@ -196,6 +196,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth)
|
||||
m_Description = a_SettingsIni.GetValueSet("Server", "Description", "MCServer - in C++!");
|
||||
m_MaxPlayers = a_SettingsIni.GetValueSetI("Server", "MaxPlayers", 100);
|
||||
m_bIsHardcore = a_SettingsIni.GetValueSetB("Server", "HardcoreEnabled", false);
|
||||
m_bAllowMultiLogin = a_SettingsIni.GetValueSetB("Server", "AllowMultiLogin", false);
|
||||
m_PlayerCount = 0;
|
||||
m_PlayerCountDiff = 0;
|
||||
|
||||
@ -298,6 +299,23 @@ int cServer::GetNumPlayers(void) const
|
||||
|
||||
|
||||
|
||||
bool cServer::IsPlayerInQueue(AString a_Username)
|
||||
{
|
||||
cCSLock Lock(m_CSClients);
|
||||
for (auto client : m_Clients)
|
||||
{
|
||||
if ((client->GetUsername()).compare(a_Username) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cServer::PrepareKeys(void)
|
||||
{
|
||||
LOGD("Generating protocol encryption keypair...");
|
||||
|
11
src/Server.h
11
src/Server.h
@ -67,6 +67,14 @@ public: // tolua_export
|
||||
int GetNumPlayers(void) const;
|
||||
void SetMaxPlayers(int a_MaxPlayers) { m_MaxPlayers = a_MaxPlayers; }
|
||||
|
||||
/** Check if the player is queued to be transferred to a World.
|
||||
Returns true is Player is found in queue. */
|
||||
bool IsPlayerInQueue(AString a_Username);
|
||||
|
||||
/** Can login more than once with same username.
|
||||
Returns false if it is not allowed, true otherwise. */
|
||||
bool DoesAllowMultiLogin(void) { return m_bAllowMultiLogin; }
|
||||
|
||||
// Hardcore mode or not:
|
||||
bool IsHardcore(void) const { return m_bIsHardcore; }
|
||||
|
||||
@ -216,6 +224,9 @@ private:
|
||||
int m_MaxPlayers;
|
||||
bool m_bIsHardcore;
|
||||
|
||||
/** True - allow same username to login more than once False - only once */
|
||||
bool m_bAllowMultiLogin;
|
||||
|
||||
cTickThread m_TickThread;
|
||||
cEvent m_RestartEvent;
|
||||
|
||||
|
@ -3669,3 +3669,4 @@ void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_Ch
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -808,7 +808,7 @@ public:
|
||||
This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long
|
||||
as at least one requests is active the chunk will be ticked). */
|
||||
void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked = true); // tolua_export
|
||||
|
||||
|
||||
private:
|
||||
|
||||
friend class cRoot;
|
||||
|
Loading…
Reference in New Issue
Block a user