added the possibility to store commands within the console and execute them later on when everything is initialised correctly - fixes several possible startup crashes and the "Support bans in server configuration"-ticket

This commit is contained in:
oy 2010-08-07 20:22:25 +02:00
parent 3f0ff1fb14
commit ad9b32b741
7 changed files with 78 additions and 20 deletions

View file

@ -1613,6 +1613,9 @@ void CClient::Run()
Input()->MouseModeRelative();
// process pending commands
m_pConsole->StoreCommands(false);
while (1)
{
int64 FrameStartTime = time_get();
@ -1915,7 +1918,7 @@ void CClient::RegisterCommands()
m_pConsole->Register("quit", "", CFGFLAG_CLIENT, Con_Quit, this, "Quit Teeworlds");
m_pConsole->Register("exit", "", CFGFLAG_CLIENT, Con_Quit, this, "Quit Teeworlds");
m_pConsole->Register("minimize", "", CFGFLAG_CLIENT, Con_Minimize, this, "Minimize Teeworlds");
m_pConsole->Register("minimize", "", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Minimize, this, "Minimize Teeworlds");
m_pConsole->Register("connect", "s", CFGFLAG_CLIENT, Con_Connect, this, "Connect to the specified host/ip");
m_pConsole->Register("disconnect", "", CFGFLAG_CLIENT, Con_Disconnect, this, "Disconnect from the server");
m_pConsole->Register("ping", "", CFGFLAG_CLIENT, Con_Ping, this, "Ping the current server");

View file

@ -44,6 +44,7 @@ public:
virtual void Register(const char *pName, const char *pParams,
int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) = 0;
virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0;
virtual void StoreCommands(bool Store) = 0;
virtual void ExecuteLine(const char *Sptr) = 0;
virtual void ExecuteLineStroked(int Stroke, const char *pStr) = 0;

View file

@ -1038,6 +1038,9 @@ int CServer::Run()
GameServer()->OnInit();
dbg_msg("server", "version %s", GameServer()->NetVersion());
// process pending commands
m_pConsole->StoreCommands(false);
// start game
{
int64 ReportTime = time_get();
@ -1325,13 +1328,13 @@ void CServer::RegisterCommands()
m_pConsole = Kernel()->RequestInterface<IConsole>();
Console()->Register("kick", "i", CFGFLAG_SERVER, ConKick, this, "");
Console()->Register("ban", "s?i", CFGFLAG_SERVER, ConBan, this, "");
Console()->Register("unban", "s", CFGFLAG_SERVER, ConUnban, this, "");
Console()->Register("bans", "", CFGFLAG_SERVER, ConBans, this, "");
Console()->Register("ban", "s?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConBan, this, "");
Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnban, this, "");
Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConBans, this, "");
Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "");
Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "");
Console()->Register("record", "s", CFGFLAG_SERVER, ConRecord, this, "");
Console()->Register("record", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, "");
Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "");
Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, "");

View file

@ -16,7 +16,8 @@ enum
{
CFGFLAG_SAVE=1,
CFGFLAG_CLIENT=2,
CFGFLAG_SERVER=4
CFGFLAG_SERVER=4,
CFGFLAG_STORE=8
};
#endif

View file

@ -1,3 +1,4 @@
#include <new>
#include <base/system.h>
#include <engine/shared/protocol.h>
#include <engine/storage.h>
@ -172,11 +173,7 @@ void CConsole::Print(const char *pStr)
void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
{
CResult Result;
char aStrokeStr[2] = {'0', 0};
if(Stroke)
aStrokeStr[0] = '1';
CResult *pResult = new(&m_ExecutionQueue.m_pLast->m_Result) CResult;
while(pStr && *pStr)
{
@ -207,37 +204,43 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
pEnd++;
}
if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0)
if(ParseStart(pResult, pStr, (pEnd-pStr) + 1) != 0)
return;
CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask);
CCommand *pCommand = FindCommand(pResult->m_pCommand, m_FlagMask);
if(pCommand)
{
int IsStrokeCommand = 0;
if(Result.m_pCommand[0] == '+')
if(pResult->m_pCommand[0] == '+')
{
// insert the stroke direction token
Result.AddArgument(aStrokeStr);
pResult->AddArgument(m_paStrokeStr[Stroke]);
IsStrokeCommand = 1;
}
if(Stroke || IsStrokeCommand)
{
if(ParseArgs(&Result, pCommand->m_pParams))
if(ParseArgs(pResult, pCommand->m_pParams))
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Invalid arguments... Usage: %s %s", pCommand->m_pName, pCommand->m_pParams);
Print(aBuf);
}
else if(m_StoreCommands && pCommand->m_Flags&CFGFLAG_STORE)
{
m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback;
m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData;
m_ExecutionQueue.AddEntry();
}
else
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
pCommand->m_pfnCallback(pResult, pCommand->m_pUserData);
}
}
else if(Stroke)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
str_format(aBuf, sizeof(aBuf), "No such command: %s.", pResult->m_pCommand);
Print(aBuf);
}
@ -390,6 +393,10 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData)
CConsole::CConsole(int FlagMask)
{
m_FlagMask = FlagMask;
m_StoreCommands = true;
m_paStrokeStr[0] = "0";
m_paStrokeStr[1] = "1";
m_ExecutionQueue.Reset();
m_pFirstCommand = 0;
m_pFirstExec = 0;
m_pPrintCallbackUserdata = 0;
@ -483,6 +490,17 @@ void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void
pCommand->m_pUserData = pChainInfo;
}
void CConsole::StoreCommands(bool Store)
{
if(!Store)
{
for(CExecutionQueue::CQueueEntry *pEntry = m_ExecutionQueue.m_pFirst; pEntry != m_ExecutionQueue.m_pLast; pEntry = pEntry->m_pNext)
pEntry->m_pfnCommandCallback(&pEntry->m_Result, pEntry->m_pCommandUserData);
m_ExecutionQueue.Reset();
}
m_StoreCommands = Store;
}
IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName, int FlagMask)
{

View file

@ -2,6 +2,7 @@
#define ENGINE_SHARED_CONSOLE_H
#include <engine/console.h>
#include "memheap.h"
class CConsole : public IConsole
{
@ -25,6 +26,8 @@ class CConsole : public IConsole
};
int m_FlagMask;
bool m_StoreCommands;
const char *m_paStrokeStr[2];
CCommand *m_pFirstCommand;
class CExecFile
@ -75,6 +78,34 @@ class CConsole : public IConsole
int ParseStart(CResult *pResult, const char *pString, int Length);
int ParseArgs(CResult *pResult, const char *pFormat);
class CExecutionQueue
{
CHeap m_Queue;
public:
struct CQueueEntry
{
CQueueEntry *m_pNext;
FCommandCallback m_pfnCommandCallback;
void *m_pCommandUserData;
CResult m_Result;
} *m_pFirst, *m_pLast;
void AddEntry()
{
CQueueEntry *pEntry = static_cast<CQueueEntry *>(m_Queue.Allocate(sizeof(CQueueEntry)));
pEntry->m_pNext = 0;
m_pLast->m_pNext = pEntry;
m_pLast = pEntry;
}
void Reset()
{
m_Queue.Reset();
m_pFirst = m_pLast = static_cast<CQueueEntry *>(m_Queue.Allocate(sizeof(CQueueEntry)));
m_pLast->m_pNext = 0;
}
} m_ExecutionQueue;
CCommand *FindCommand(const char *pName, int FlagMask);
public:
@ -86,6 +117,7 @@ public:
virtual void ParseArguments(int NumArgs, const char **ppArguments);
virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp);
virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser);
virtual void StoreCommands(bool Store);
virtual void ExecuteLine(const char *pStr);
virtual void ExecuteFile(const char *pFilename);

View file

@ -948,8 +948,8 @@ void CGameContext::OnConsoleInit()
Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "");
Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "");
Console()->Register("change_map", "r", CFGFLAG_SERVER, ConChangeMap, this, "");
Console()->Register("restart", "?i", CFGFLAG_SERVER, ConRestart, this, "");
Console()->Register("change_map", "r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "");
Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "");
Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "");
Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, "");
Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConSetTeam, this, "");