about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authoroy <Tom_Adams@web.de>2011-03-25 11:49:35 +0100
committeroy <Tom_Adams@web.de>2011-03-25 11:49:35 +0100
commit359b806e959fbdced610c2d84d1e12dfe7b58a7e (patch)
treef21443f47c73b40f6c64b6055354a4e36e171244 /src
parenta4580d451f8e4584f9aaa7b6ebe3380488ee4455 (diff)
downloadzcatch-359b806e959fbdced610c2d84d1e12dfe7b58a7e.tar.gz
zcatch-359b806e959fbdced610c2d84d1e12dfe7b58a7e.zip
added remove_vote command. Closes #47
Diffstat (limited to 'src')
-rw-r--r--src/game/client/components/voting.cpp52
-rw-r--r--src/game/client/components/voting.h3
-rw-r--r--src/game/client/gameclient.cpp1
-rw-r--r--src/game/server/gamecontext.cpp71
-rw-r--r--src/game/server/gamecontext.h1
5 files changed, 121 insertions, 7 deletions
diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp
index 1f99f4b3..808b6669 100644
--- a/src/game/client/components/voting.cpp
+++ b/src/game/client/components/voting.cpp
@@ -100,6 +100,9 @@ void CVoting::ClearOptions()
 	
 	m_pFirst = 0;
 	m_pLast = 0;
+
+	m_pRecycleFirst = 0;
+	m_pRecycleLast = 0;
 }
 
 void CVoting::OnReset()
@@ -144,11 +147,23 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg)
 	{
 		ClearOptions();
 	}
-	else if(MsgType == NETMSGTYPE_SV_VOTEOPTION)
+	else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONADD)
 	{
-		CNetMsg_Sv_VoteOption *pMsg = (CNetMsg_Sv_VoteOption *)pRawMsg;
+		CNetMsg_Sv_VoteOptionAdd *pMsg = (CNetMsg_Sv_VoteOptionAdd *)pRawMsg;
 	
-		CVoteOption *pOption = (CVoteOption *)m_Heap.Allocate(sizeof(CVoteOption));
+		CVoteOption *pOption;
+		if(m_pRecycleFirst)
+		{
+			pOption = m_pRecycleFirst;
+			m_pRecycleFirst = m_pRecycleFirst->m_pNext;
+			if(m_pRecycleFirst)
+				m_pRecycleFirst->m_pPrev = 0;
+			else
+				m_pRecycleLast = 0;
+		}
+		else
+			pOption = (CVoteOption *)m_Heap.Allocate(sizeof(CVoteOption));
+
 		pOption->m_pNext = 0;
 		pOption->m_pPrev = m_pLast;
 		if(pOption->m_pPrev)
@@ -159,6 +174,37 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg)
 		
 		str_copy(pOption->m_aDescription, pMsg->m_pDescription, sizeof(pOption->m_aDescription));
 	}
+	else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONREMOVE)
+	{
+		CNetMsg_Sv_VoteOptionRemove *pMsg = (CNetMsg_Sv_VoteOptionRemove *)pRawMsg;
+	
+		for(CVoteOption *pOption = m_pFirst; pOption; pOption = pOption->m_pNext)
+		{
+			if(str_comp(pOption->m_aDescription, pMsg->m_pDescription) == 0)
+			{
+				// remove it from the list
+				if(m_pFirst == pOption)
+					m_pFirst = m_pFirst->m_pNext;
+				if(m_pLast == pOption)
+					m_pLast = m_pLast->m_pPrev;
+				if(pOption->m_pPrev)
+					pOption->m_pPrev->m_pNext = pOption->m_pNext;
+				if(pOption->m_pNext)
+					pOption->m_pNext->m_pPrev = pOption->m_pPrev;
+
+				// add it to recycle list
+				pOption->m_pNext = 0;
+				pOption->m_pPrev = m_pRecycleLast;
+				if(pOption->m_pPrev)
+					pOption->m_pPrev->m_pNext = pOption;
+				m_pRecycleLast = pOption;
+				if(!m_pRecycleFirst)
+					m_pRecycleLast = pOption;
+
+				break;
+			}
+		}
+	}
 }
 
 void CVoting::OnRender()
diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h
index 10e0512c..9687d895 100644
--- a/src/game/client/components/voting.h
+++ b/src/game/client/components/voting.h
@@ -34,6 +34,9 @@ public:
 	CVoteOption *m_pFirst;
 	CVoteOption *m_pLast;
 
+	CVoteOption *m_pRecycleFirst;
+	CVoteOption *m_pRecycleLast;
+
 	CVoting();
 	virtual void OnReset();
 	virtual void OnConsoleInit();
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp
index c6419b34..4d80e0f1 100644
--- a/src/game/client/gameclient.cpp
+++ b/src/game/client/gameclient.cpp
@@ -198,6 +198,7 @@ void CGameClient::OnConsoleInit()
 	Console()->Register("set_team", "ii", CFGFLAG_SERVER, 0, 0, "Set team of player to team");
 	Console()->Register("set_team_all", "i", CFGFLAG_SERVER, 0, 0, "Set team of all players to team");
 	Console()->Register("add_vote", "sr", CFGFLAG_SERVER, 0, 0, "Add a voting option");
+	Console()->Register("remove_vote", "s", CFGFLAG_SERVER, 0, 0, "remove a voting option");
 	Console()->Register("clear_votes", "", CFGFLAG_SERVER, 0, 0, "Clears the voting options");
 	Console()->Register("vote", "r", CFGFLAG_SERVER, 0, 0, "Force a vote to yes/no");
 
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index f00d2b3c..4c236832 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -804,7 +804,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 		CVoteOption *pCurrent = m_pVoteOptionFirst;
 		while(pCurrent)
 		{
-			CNetMsg_Sv_VoteOption OptionMsg;
+			CNetMsg_Sv_VoteOptionAdd OptionMsg;
 			OptionMsg.m_pDescription = pCurrent->m_aDescription;
 			Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
 			pCurrent = pCurrent->m_pNext;
@@ -984,7 +984,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
 	CGameContext::CVoteOption *pOption = pSelf->m_pVoteOptionFirst;
 	while(pOption)
 	{
-		if(str_comp_nocase(pDescription, pOption->m_aCommand) == 0)
+		if(str_comp_nocase(pDescription, pOption->m_aDescription) == 0)
 		{
 			char aBuf[256];
 			str_format(aBuf, sizeof(aBuf), "option '%s' already exists", pDescription);
@@ -1012,8 +1012,70 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
 	str_format(aBuf, sizeof(aBuf), "added option '%s' '%s'", pOption->m_aDescription, pOption->m_aCommand);
 	pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
 
-	// send added option to the clients
-	CNetMsg_Sv_VoteOption OptionMsg;
+	// inform clients about added option
+	CNetMsg_Sv_VoteOptionAdd OptionMsg;
+	OptionMsg.m_pDescription = pOption->m_aDescription;
+	pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1);
+}
+
+void CGameContext::ConRemoveVote(IConsole::IResult *pResult, void *pUserData)
+{
+	CGameContext *pSelf = (CGameContext *)pUserData;
+	const char *pDescription = pResult->GetString(0);
+	
+	// check for valid option
+	CGameContext::CVoteOption *pOption = pSelf->m_pVoteOptionFirst;
+	while(pOption)
+	{
+		if(str_comp_nocase(pDescription, pOption->m_aDescription) == 0)
+			break;
+		pOption = pOption->m_pNext;
+	}
+	if(!pOption)
+	{
+		char aBuf[256];
+		str_format(aBuf, sizeof(aBuf), "option '%s' does not exist", pDescription);
+		pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
+		return;
+	}
+	
+	// TODO: improve this
+	// remove the option
+	char aBuf[256];
+	str_format(aBuf, sizeof(aBuf), "removed option '%s' '%s'", pOption->m_aDescription, pOption->m_aCommand);
+	pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
+
+	CHeap *pVoteOptionHeap = new CHeap();

+	CVoteOption *pVoteOptionFirst = 0;
+	CVoteOption *pVoteOptionLast = 0;

+	for(CVoteOption *pSrc = pSelf->m_pVoteOptionFirst; pSrc; pSrc = pSrc->m_pNext)
+	{
+		if(pSrc == pOption)
+			continue;
+
+		// copy option
+		int Len = str_length(pSrc->m_aCommand);
+		CVoteOption *pDst = (CGameContext::CVoteOption *)pVoteOptionHeap->Allocate(sizeof(CGameContext::CVoteOption) + Len);
+		pDst->m_pNext = 0;
+		pDst->m_pPrev = pVoteOptionLast;
+		if(pDst->m_pPrev)
+			pDst->m_pPrev->m_pNext = pDst;
+		pVoteOptionLast = pDst;
+		if(!pVoteOptionFirst)
+			pVoteOptionFirst = pDst;
+		
+		str_copy(pDst->m_aDescription, pSrc->m_aDescription, sizeof(pDst->m_aDescription));
+		mem_copy(pDst->m_aCommand, pSrc->m_aCommand, Len+1);
+	}

+

+	// clean up

+	delete pSelf->m_pVoteOptionHeap;

+	pSelf->m_pVoteOptionHeap = pVoteOptionHeap;
+	pSelf->m_pVoteOptionFirst = pVoteOptionFirst;
+	pSelf->m_pVoteOptionLast = pVoteOptionLast;
+
+	// inform clients about removed option
+	CNetMsg_Sv_VoteOptionRemove OptionMsg;
 	OptionMsg.m_pDescription = pOption->m_aDescription;
 	pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1);
 }
@@ -1073,6 +1135,7 @@ void CGameContext::OnConsoleInit()
 	Console()->Register("set_team_all", "i", CFGFLAG_SERVER, ConSetTeamAll, this, "");
 
 	Console()->Register("add_vote", "sr", CFGFLAG_SERVER, ConAddVote, this, "");
+	Console()->Register("remove_vote", "s", CFGFLAG_SERVER, ConRemoveVote, this, "");
 	Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "");
 	Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, "");
 
diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h
index 472f29f8..3dc1e99f 100644
--- a/src/game/server/gamecontext.h
+++ b/src/game/server/gamecontext.h
@@ -54,6 +54,7 @@ class CGameContext : public IGameServer
 	static void ConSetTeam(IConsole::IResult *pResult, void *pUserData);
 	static void ConSetTeamAll(IConsole::IResult *pResult, void *pUserData);
 	static void ConAddVote(IConsole::IResult *pResult, void *pUserData);
+	static void ConRemoveVote(IConsole::IResult *pResult, void *pUserData);
 	static void ConClearVotes(IConsole::IResult *pResult, void *pUserData);
 	static void ConVote(IConsole::IResult *pResult, void *pUserData);
 	static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);