about summary refs log tree commit diff
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2010-08-07 20:22:25 +0200
committeroy <Tom_Adams@web.de>2010-08-07 20:22:25 +0200
commitad9b32b7417d0837c485b6c9b802cc90aa51c521 (patch)
treefb2c0cd8d68f58bbbd1e0d895cb82086ea824fe7
parent3f0ff1fb1404efcb312a6bfcef0beb4b6a0d92ef (diff)
downloadzcatch-ad9b32b7417d0837c485b6c9b802cc90aa51c521.tar.gz
zcatch-ad9b32b7417d0837c485b6c9b802cc90aa51c521.zip
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
-rw-r--r--src/engine/client/client.cpp5
-rw-r--r--src/engine/console.h1
-rw-r--r--src/engine/server/server.cpp11
-rw-r--r--src/engine/shared/config.h3
-rw-r--r--src/engine/shared/console.cpp42
-rw-r--r--src/engine/shared/console.h32
-rw-r--r--src/game/server/gamecontext.cpp4
7 files changed, 78 insertions, 20 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index 90bb70d3..4ab8ee60 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -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");
diff --git a/src/engine/console.h b/src/engine/console.h
index 34fa4272..05034734 100644
--- a/src/engine/console.h
+++ b/src/engine/console.h
@@ -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;
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 847d07ce..0fd314d0 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -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, "");
diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h
index 10a54004..ccece08c 100644
--- a/src/engine/shared/config.h
+++ b/src/engine/shared/config.h
@@ -16,7 +16,8 @@ enum
 {
 	CFGFLAG_SAVE=1,
 	CFGFLAG_CLIENT=2,
-	CFGFLAG_SERVER=4
+	CFGFLAG_SERVER=4,
+	CFGFLAG_STORE=8
 };
 
 #endif
diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp
index b7850bea..a6cf4d0b 100644
--- a/src/engine/shared/console.cpp
+++ b/src/engine/shared/console.cpp
@@ -1,3 +1,4 @@
+#include <new>
 #include <base/system.h>
 #include <engine/shared/protocol.h>
 #include <engine/storage.h>
@@ -172,12 +173,8 @@ void CConsole::Print(const char *pStr)
 
 void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
 {
-	CResult Result;
+	CResult *pResult = new(&m_ExecutionQueue.m_pLast->m_Result) CResult;
 	
-	char aStrokeStr[2] = {'0', 0};
-	if(Stroke)
-		aStrokeStr[0] = '1';
-
 	while(pStr && *pStr)
 	{
 		const char *pEnd = 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)
 {
diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h
index 9064fa86..9c127ae0 100644
--- a/src/engine/shared/console.h
+++ b/src/engine/shared/console.h
@@ -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);
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index e9cce458..8b8db59a 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -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, "");