Merge pull request #8243 from Robyt3/Console-Scrolling-Fix

Fix potential client crash and console not keeping scrolling position when console backlog is full
This commit is contained in:
Dennis Felsing 2024-04-21 15:46:59 +00:00 committed by GitHub
commit 18d8e987f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 8 deletions

View file

@ -123,11 +123,21 @@ void *CRingBufferBase::Allocate(int Size)
return (void *)(pBlock + 1);
}
void CRingBufferBase::SetPopCallback(std::function<void(void *pCurrent)> PopCallback)
{
m_PopCallback = std::move(PopCallback);
}
int CRingBufferBase::PopFirst()
{
if(m_pConsume->m_Free)
return 0;
if(m_PopCallback)
{
m_PopCallback(m_pConsume + 1);
}
// set the free flag
m_pConsume->m_Free = 1;

View file

@ -5,6 +5,8 @@
#include <base/system.h>
#include <functional>
class CRingBufferBase
{
class CItem
@ -25,6 +27,8 @@ class CRingBufferBase
int m_Size;
int m_Flags;
std::function<void(void *pCurrent)> m_PopCallback = nullptr;
CItem *NextBlock(CItem *pItem);
CItem *PrevBlock(CItem *pItem);
CItem *MergeBack(CItem *pItem);
@ -39,6 +43,7 @@ protected:
void Init(void *pMemory, int Size, int Flags);
int PopFirst();
void SetPopCallback(const std::function<void(void *pCurrent)> PopCallback);
public:
enum
@ -55,6 +60,12 @@ class CTypedRingBuffer : public CRingBufferBase
public:
T *Allocate(int Size) { return (T *)CRingBufferBase::Allocate(Size); }
int PopFirst() { return CRingBufferBase::PopFirst(); }
void SetPopCallback(std::function<void(T *pCurrent)> PopCallback)
{
CRingBufferBase::SetPopCallback([PopCallback](void *pCurrent) {
PopCallback((T *)pCurrent);
});
}
T *Prev(T *pCurrent) { return (T *)CRingBufferBase::Prev(pCurrent); }
T *Next(T *pCurrent) { return (T *)CRingBufferBase::Next(pCurrent); }

View file

@ -208,6 +208,13 @@ CGameConsole::CInstance::CInstance(int Type)
m_IsCommand = false;
m_Backlog.SetPopCallback([this](CBacklogEntry *pEntry) {
if(pEntry->m_LineCount != -1)
{
m_NewLineCounter -= pEntry->m_LineCount;
}
});
m_Input.SetClipboardLineCallback([this](const char *pStr) { ExecuteLine(pStr); });
m_CurrentMatchIndex = -1;
@ -236,7 +243,7 @@ void CGameConsole::CInstance::ClearBacklog()
void CGameConsole::CInstance::UpdateBacklogTextAttributes()
{
// Pending backlog entries are not handled because they don't have text attributes yet.
for(CInstance::CBacklogEntry *pEntry = m_Backlog.First(); pEntry; pEntry = m_Backlog.Next(pEntry))
for(CBacklogEntry *pEntry = m_Backlog.First(); pEntry; pEntry = m_Backlog.Next(pEntry))
{
UpdateEntryTextAttributes(pEntry);
}
@ -244,27 +251,29 @@ void CGameConsole::CInstance::UpdateBacklogTextAttributes()
void CGameConsole::CInstance::PumpBacklogPending()
{
std::vector<CInstance::CBacklogEntry *> vpEntries;
{
// We must ensure that no log messages are printed while owning
// m_BacklogPendingLock or this will result in a dead lock.
const CLockScope LockScopePending(m_BacklogPendingLock);
for(CInstance::CBacklogEntry *pPendingEntry = m_BacklogPending.First(); pPendingEntry; pPendingEntry = m_BacklogPending.Next(pPendingEntry))
for(CBacklogEntry *pPendingEntry = m_BacklogPending.First(); pPendingEntry; pPendingEntry = m_BacklogPending.Next(pPendingEntry))
{
const size_t EntrySize = sizeof(CBacklogEntry) + pPendingEntry->m_Length;
CBacklogEntry *pEntry = m_Backlog.Allocate(EntrySize);
mem_copy(pEntry, pPendingEntry, EntrySize);
vpEntries.push_back(pEntry);
}
m_BacklogPending.Init();
}
// Update text attributes and count number of added lines
m_pGameConsole->Ui()->MapScreen();
for(CInstance::CBacklogEntry *pEntry : vpEntries)
for(CBacklogEntry *pEntry = m_Backlog.First(); pEntry; pEntry = m_Backlog.Next(pEntry))
{
UpdateEntryTextAttributes(pEntry);
m_NewLineCounter += pEntry->m_LineCount;
if(pEntry->m_LineCount == -1)
{
UpdateEntryTextAttributes(pEntry);
m_NewLineCounter += pEntry->m_LineCount;
}
}
}
@ -1133,7 +1142,7 @@ void CGameConsole::OnRender()
}
pConsole->PumpBacklogPending();
if(pConsole->m_NewLineCounter > 0)
if(pConsole->m_NewLineCounter != 0)
{
pConsole->UpdateSearch();
@ -1143,6 +1152,8 @@ void CGameConsole::OnRender()
pConsole->m_BacklogCurLine += pConsole->m_NewLineCounter;
pConsole->m_BacklogLastActiveLine += pConsole->m_NewLineCounter;
}
if(pConsole->m_NewLineCounter < 0)
pConsole->m_NewLineCounter = 0;
}
// render console log (current entry, status, wrap lines)