Add add_map_votes command for easier local map testing

No need to tell new players how to manually add a vote or load a map
from rcon
This commit is contained in:
def 2020-10-18 00:05:59 +02:00
parent 54c7a5bba5
commit 81bc68d9d0
4 changed files with 68 additions and 18 deletions

View file

@ -127,10 +127,7 @@ sv_reset_file "reset.cfg"
#
# You can learn more about tunes on http://ddnet.tw/settingscommands/#tunings
add_vote "Map: Gold Mine" "change_map \"Gold Mine\""
add_vote "Map: LearnToPlay" "change_map \"LearnToPlay\""
add_vote "Map: Sunny Side Up" "change_map \"Sunny Side Up\""
add_vote "Map: Tsunami" "change_map \"Tsunami\""
add_map_votes
add_vote "" "info"
add_vote "Option: Normal gravity" "tune gravity 0.50"
add_vote "Option: Moon gravity" "tune gravity 0.25"

View file

@ -245,6 +245,7 @@ void CGameClient::OnConsoleInit()
Console()->Register("remove_vote", "s[name]", CFGFLAG_SERVER, 0, 0, "remove a voting option");
Console()->Register("force_vote", "s[name] s[command] ?r[reason]", CFGFLAG_SERVER, 0, 0, "Force a voting option");
Console()->Register("clear_votes", "", CFGFLAG_SERVER, 0, 0, "Clears the voting options");
Console()->Register("add_map_votes", "", CFGFLAG_SERVER, 0, 0, "Automatically adds voting options for all maps");
Console()->Register("vote", "r['yes'|'no']", CFGFLAG_SERVER, 0, 0, "Force a vote to yes/no");
Console()->Register("swap_teams", "", CFGFLAG_SERVER, 0, 0, "Swap the current teams");
Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, 0, 0, "Shuffle the current teams");

View file

@ -2696,18 +2696,23 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
const char *pDescription = pResult->GetString(0);
const char *pCommand = pResult->GetString(1);
if(pSelf->m_NumVoteOptions == MAX_VOTE_OPTIONS)
pSelf->AddVote(pDescription, pCommand);
}
void CGameContext::AddVote(const char *pDescription, const char *pCommand)
{
if(m_NumVoteOptions == MAX_VOTE_OPTIONS)
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "maximum number of vote options reached");
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "maximum number of vote options reached");
return;
}
// check for valid option
if(!pSelf->Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH)
if(!Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "skipped invalid command '%s'", pCommand);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return;
}
while(*pDescription && *pDescription == ' ')
@ -2716,42 +2721,42 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "skipped invalid option '%s'", pDescription);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return;
}
// check for duplicate entry
CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst;
CVoteOptionServer *pOption = m_pVoteOptionFirst;
while(pOption)
{
if(str_comp_nocase(pDescription, pOption->m_aDescription) == 0)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "option '%s' already exists", pDescription);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return;
}
pOption = pOption->m_pNext;
}
// add the option
++pSelf->m_NumVoteOptions;
++m_NumVoteOptions;
int Len = str_length(pCommand);
pOption = (CVoteOptionServer *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len);
pOption = (CVoteOptionServer *)m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len);
pOption->m_pNext = 0;
pOption->m_pPrev = pSelf->m_pVoteOptionLast;
pOption->m_pPrev = m_pVoteOptionLast;
if(pOption->m_pPrev)
pOption->m_pPrev->m_pNext = pOption;
pSelf->m_pVoteOptionLast = pOption;
if(!pSelf->m_pVoteOptionFirst)
pSelf->m_pVoteOptionFirst = pOption;
m_pVoteOptionLast = pOption;
if(!m_pVoteOptionFirst)
m_pVoteOptionFirst = pOption;
str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription));
mem_copy(pOption->m_aCommand, pCommand, Len + 1);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "added option '%s' '%s'", pOption->m_aDescription, pOption->m_aCommand);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}
void CGameContext::ConRemoveVote(IConsole::IResult *pResult, void *pUserData)
@ -2915,6 +2920,49 @@ void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData)
}
}
struct CMapNameItem
{
char m_aName[MAX_PATH_LENGTH - 4];
bool operator<(const CMapNameItem &Other) const { return str_comp_nocase(m_aName, Other.m_aName) < 0; }
};
void CGameContext::ConAddMapVotes(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
sorted_array<CMapNameItem> MapList;
pSelf->Storage()->ListDirectory(IStorage::TYPE_ALL, "maps", MapScan, &MapList);
for(int i = 0; i < MapList.size(); i++)
{
char aDescription[64];
str_format(aDescription, sizeof(aDescription), "Map: %s", MapList[i].m_aName);
char aCommand[MAX_PATH_LENGTH + 10];
str_format(aCommand, sizeof(aCommand), "change_map \"%s\"", MapList[i].m_aName);
pSelf->AddVote(aDescription, aCommand);
}
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "added maps to votes");
}
int CGameContext::MapScan(const char *pName, int IsDir, int DirType, void *pUserData)
{
sorted_array<CMapNameItem> *pMapList = (sorted_array<CMapNameItem> *)pUserData;
if(IsDir || !str_endswith(pName, ".map"))
return 0;
CMapNameItem Item;
int Length = str_length(pName);
str_copy(Item.m_aName, pName, minimum(static_cast<int>(sizeof(Item.m_aName)), Length - 3));
pMapList->add(Item);
return 0;
}
void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
@ -2973,6 +3021,7 @@ void CGameContext::OnConsoleInit()
Console()->Register("remove_vote", "r[name]", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option");
Console()->Register("force_vote", "s[name] s[command] ?r[reason]", CFGFLAG_SERVER, ConForceVote, this, "Force a voting option");
Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "Clears the voting options");
Console()->Register("add_map_votes", "", CFGFLAG_SERVER, ConAddMapVotes, this, "Automatically adds voting options for all maps");
Console()->Register("vote", "r['yes'|'no']", CFGFLAG_SERVER, ConVote, this, "Force a vote to yes/no");
Console()->Register("dump_antibot", "", CFGFLAG_SERVER, ConDumpAntibot, this, "Dumps the antibot status");

View file

@ -114,6 +114,7 @@ class CGameContext : public IGameServer
static void ConRemoveVote(IConsole::IResult *pResult, void *pUserData);
static void ConForceVote(IConsole::IResult *pResult, void *pUserData);
static void ConClearVotes(IConsole::IResult *pResult, void *pUserData);
static void ConAddMapVotes(IConsole::IResult *pResult, void *pUserData);
static void ConVote(IConsole::IResult *pResult, void *pUserData);
static void ConVoteNo(IConsole::IResult *pResult, void *pUserData);
static void ConDrySave(IConsole::IResult *pResult, void *pUserData);
@ -122,6 +123,8 @@ class CGameContext : public IGameServer
CGameContext(int Resetting);
void Construct(int Resetting);
void AddVote(const char *pDescription, const char *pCommand);
static int MapScan(const char *pName, int IsDir, int DirType, void *pUserData);
bool m_Resetting;