mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Improvement of the automatic completion of player names in chat
This commit is contained in:
parent
5d5aa10515
commit
92eaccfcb2
|
@ -323,6 +323,32 @@ bool CChat::OnInput(IInput::CEvent Event)
|
||||||
str_truncate(m_aCompletionBuffer, sizeof(m_aCompletionBuffer), m_Input.GetString() + m_PlaceholderOffset, m_PlaceholderLength);
|
str_truncate(m_aCompletionBuffer, sizeof(m_aCompletionBuffer), m_Input.GetString() + m_PlaceholderOffset, m_PlaceholderLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!m_CompletionUsed && m_aCompletionBuffer[0] != '/')
|
||||||
|
{
|
||||||
|
// Create the completion list of player names through which the player can iterate
|
||||||
|
const char *PlayerName, *FoundInput;
|
||||||
|
m_PlayerCompletionListLength = 0;
|
||||||
|
for(auto &PlayerInfo : m_pClient->m_Snap.m_paInfoByName)
|
||||||
|
{
|
||||||
|
if(PlayerInfo)
|
||||||
|
{
|
||||||
|
PlayerName = m_pClient->m_aClients[PlayerInfo->m_ClientID].m_aName;
|
||||||
|
FoundInput = str_utf8_find_nocase(PlayerName, m_aCompletionBuffer);
|
||||||
|
if(FoundInput != 0)
|
||||||
|
{
|
||||||
|
m_aPlayerCompletionList[m_PlayerCompletionListLength].ClientID = PlayerInfo->m_ClientID;
|
||||||
|
// The score for suggesting a player name is determined by the distance of the search input to the beginning of the player name
|
||||||
|
m_aPlayerCompletionList[m_PlayerCompletionListLength].Score = (int)(FoundInput - PlayerName);
|
||||||
|
m_PlayerCompletionListLength++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::stable_sort(m_aPlayerCompletionList, m_aPlayerCompletionList + m_PlayerCompletionListLength,
|
||||||
|
[](const CRateablePlayer &p1, const CRateablePlayer &p2) -> bool {
|
||||||
|
return p1.Score < p2.Score;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if(m_aCompletionBuffer[0] == '/')
|
if(m_aCompletionBuffer[0] == '/')
|
||||||
{
|
{
|
||||||
CCommand *pCompletionCommand = 0;
|
CCommand *pCompletionCommand = 0;
|
||||||
|
@ -395,50 +421,34 @@ bool CChat::OnInput(IInput::CEvent Event)
|
||||||
{
|
{
|
||||||
// find next possible name
|
// find next possible name
|
||||||
const char *pCompletionString = 0;
|
const char *pCompletionString = 0;
|
||||||
|
if(m_PlayerCompletionListLength > 0)
|
||||||
if(m_ReverseTAB && m_CompletionUsed)
|
|
||||||
m_CompletionChosen--;
|
|
||||||
else if(!m_ReverseTAB)
|
|
||||||
m_CompletionChosen++;
|
|
||||||
m_CompletionChosen = (m_CompletionChosen + 2 * MAX_CLIENTS) % (2 * MAX_CLIENTS);
|
|
||||||
|
|
||||||
m_CompletionUsed = true;
|
|
||||||
|
|
||||||
for(int i = 0; i < 2 * MAX_CLIENTS; ++i)
|
|
||||||
{
|
{
|
||||||
int SearchType;
|
// We do this in a loop, if a player left the game during the repeated pressing of Tab, they are skipped
|
||||||
int Index;
|
CGameClient::CClientData *CompletionClientData;
|
||||||
|
for(int i = 0; i < m_PlayerCompletionListLength; ++i)
|
||||||
if(m_ReverseTAB)
|
|
||||||
{
|
{
|
||||||
SearchType = ((m_CompletionChosen - i + 2 * MAX_CLIENTS) % (2 * MAX_CLIENTS)) / MAX_CLIENTS;
|
if(m_ReverseTAB && m_CompletionUsed)
|
||||||
Index = (m_CompletionChosen - i + MAX_CLIENTS) % MAX_CLIENTS;
|
{
|
||||||
}
|
m_CompletionChosen--;
|
||||||
else
|
}
|
||||||
{
|
else if(!m_ReverseTAB)
|
||||||
SearchType = ((m_CompletionChosen + i) % (2 * MAX_CLIENTS)) / MAX_CLIENTS;
|
{
|
||||||
Index = (m_CompletionChosen + i) % MAX_CLIENTS;
|
m_CompletionChosen++;
|
||||||
}
|
}
|
||||||
|
if(m_CompletionChosen < 0)
|
||||||
|
{
|
||||||
|
m_CompletionChosen += m_PlayerCompletionListLength;
|
||||||
|
}
|
||||||
|
m_CompletionChosen %= m_PlayerCompletionListLength;
|
||||||
|
m_CompletionUsed = true;
|
||||||
|
|
||||||
if(!m_pClient->m_Snap.m_paInfoByName[Index])
|
CompletionClientData = &m_pClient->m_aClients[m_aPlayerCompletionList[m_CompletionChosen].ClientID];
|
||||||
continue;
|
if(!CompletionClientData->m_Active)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int Index2 = m_pClient->m_Snap.m_paInfoByName[Index]->m_ClientID;
|
pCompletionString = CompletionClientData->m_aName;
|
||||||
|
|
||||||
bool Found = false;
|
|
||||||
if(SearchType == 1)
|
|
||||||
{
|
|
||||||
if(str_utf8_comp_nocase_num(m_pClient->m_aClients[Index2].m_aName, m_aCompletionBuffer, str_length(m_aCompletionBuffer)) &&
|
|
||||||
str_utf8_find_nocase(m_pClient->m_aClients[Index2].m_aName, m_aCompletionBuffer))
|
|
||||||
Found = true;
|
|
||||||
}
|
|
||||||
else if(!str_utf8_comp_nocase_num(m_pClient->m_aClients[Index2].m_aName, m_aCompletionBuffer, str_length(m_aCompletionBuffer)))
|
|
||||||
Found = true;
|
|
||||||
|
|
||||||
if(Found)
|
|
||||||
{
|
|
||||||
pCompletionString = m_pClient->m_aClients[Index2].m_aName;
|
|
||||||
m_CompletionChosen = Index + SearchType * MAX_CLIENTS;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#define GAME_CLIENT_COMPONENTS_CHAT_H
|
#define GAME_CLIENT_COMPONENTS_CHAT_H
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
#include <engine/shared/ringbuffer.h>
|
#include <engine/shared/ringbuffer.h>
|
||||||
|
|
||||||
#include <game/client/component.h>
|
#include <game/client/component.h>
|
||||||
#include <game/client/lineinput.h>
|
#include <game/client/lineinput.h>
|
||||||
|
|
||||||
#include <game/client/skin.h>
|
#include <game/client/skin.h>
|
||||||
|
|
||||||
class CChat : public CComponent
|
class CChat : public CComponent
|
||||||
|
@ -80,6 +80,13 @@ class CChat : public CComponent
|
||||||
char m_aCompletionBuffer[256];
|
char m_aCompletionBuffer[256];
|
||||||
int m_PlaceholderOffset;
|
int m_PlaceholderOffset;
|
||||||
int m_PlaceholderLength;
|
int m_PlaceholderLength;
|
||||||
|
struct CRateablePlayer
|
||||||
|
{
|
||||||
|
int ClientID;
|
||||||
|
int Score;
|
||||||
|
};
|
||||||
|
CRateablePlayer m_aPlayerCompletionList[MAX_CLIENTS];
|
||||||
|
int m_PlayerCompletionListLength;
|
||||||
|
|
||||||
struct CCommand
|
struct CCommand
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue