merged "List maps" by Learath2 and cinaera. skipped redundant "maps" command. closes #1086

This commit is contained in:
oy 2019-01-12 20:56:34 +01:00
parent 981cba1605
commit bc38f67750
10 changed files with 297 additions and 6 deletions

View file

@ -29,5 +29,7 @@ for filename in sys.argv[1:]:
f += cstrip([l.strip() for l in open(filename, "rb")]) f += cstrip([l.strip() for l in open(filename, "rb")])
hash = hashlib.md5(f).hexdigest().lower()[16:] hash = hashlib.md5(f).hexdigest().lower()[16:]
#TODO 0.7: improve nethash creation #TODO 0.8: improve nethash creation
if hash == "0a027ded5791b521":
hash = "802f1be60a05665f"
print('#define GAME_NETVERSION_HASH "%s"' % hash) print('#define GAME_NETVERSION_HASH "%s"' % hash)

View file

@ -509,6 +509,7 @@ void CClient::Connect(const char *pAddress)
} }
m_RconAuthed = 0; m_RconAuthed = 0;
m_UseTempRconCommands = 0;
if(m_ServerAddress.port == 0) if(m_ServerAddress.port == 0)
m_ServerAddress.port = Port; m_ServerAddress.port = Port;
m_NetClient.Connect(&m_ServerAddress); m_NetClient.Connect(&m_ServerAddress);
@ -1175,6 +1176,18 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(Unpacker.Error() == 0) if(Unpacker.Error() == 0)
m_pConsole->DeregisterTemp(pName); m_pConsole->DeregisterTemp(pName);
} }
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAPLIST_ENTRY_ADD)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->RegisterTempMap(pName);
}
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAPLIST_ENTRY_REM)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->DeregisterTempMap(pName);
}
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_ON) else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_ON)
{ {
m_RconAuthed = 1; m_RconAuthed = 1;
@ -1186,6 +1199,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(m_UseTempRconCommands) if(m_UseTempRconCommands)
m_pConsole->DeregisterTempAll(); m_pConsole->DeregisterTempAll();
m_UseTempRconCommands = 0; m_UseTempRconCommands = 0;
m_pConsole->DeregisterTempMapAll();
} }
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE) else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE)
{ {

View file

@ -24,6 +24,8 @@ public:
TEMPCMD_HELP_LENGTH=96, TEMPCMD_HELP_LENGTH=96,
TEMPCMD_PARAMS_LENGTH=16, TEMPCMD_PARAMS_LENGTH=16,
TEMPMAP_NAME_LENGTH = 32,
MAX_PRINT_CB=4, MAX_PRINT_CB=4,
}; };
@ -67,12 +69,16 @@ public:
virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int Flagmask) const = 0; virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int Flagmask) const = 0;
virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp) = 0; virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp) = 0;
virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser) = 0; virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser) = 0;
virtual void PossibleMaps(const char *pStr, FPossibleCallback pfnCallback, void *pUser) = 0;
virtual void ParseArguments(int NumArgs, const char **ppArguments) = 0; virtual void ParseArguments(int NumArgs, const char **ppArguments) = 0;
virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) = 0; virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) = 0;
virtual void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp) = 0; virtual void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp) = 0;
virtual void DeregisterTemp(const char *pName) = 0; virtual void DeregisterTemp(const char *pName) = 0;
virtual void DeregisterTempAll() = 0; virtual void DeregisterTempAll() = 0;
virtual void RegisterTempMap(const char *pName) = 0;
virtual void DeregisterTempMap(const char *pName) = 0;
virtual void DeregisterTempMapAll() = 0;
virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0; virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0;
virtual void StoreCommands(bool Store) = 0; virtual void StoreCommands(bool Store) = 0;

View file

@ -280,6 +280,10 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
m_pCurrentMapData = 0; m_pCurrentMapData = 0;
m_CurrentMapSize = 0; m_CurrentMapSize = 0;
m_NumMapEntries = 0;
m_pFirstMapEntry = 0;
m_pLastMapEntry = 0;
m_MapReload = 0; m_MapReload = 0;
m_RconClientID = IServer::RCON_CID_SERV; m_RconClientID = IServer::RCON_CID_SERV;
@ -664,6 +668,7 @@ int CServer::NewClientCallback(int ClientID, void *pUser)
pThis->m_aClients[ClientID].m_Authed = AUTHED_NO; pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
pThis->m_aClients[ClientID].m_AuthTries = 0; pThis->m_aClients[ClientID].m_AuthTries = 0;
pThis->m_aClients[ClientID].m_pRconCmdToSend = 0; pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
pThis->m_aClients[ClientID].m_pMapListEntryToSend = 0;
pThis->m_aClients[ClientID].m_NoRconNote = false; pThis->m_aClients[ClientID].m_NoRconNote = false;
pThis->m_aClients[ClientID].m_Quitting = false; pThis->m_aClients[ClientID].m_Quitting = false;
pThis->m_aClients[ClientID].Reset(); pThis->m_aClients[ClientID].Reset();
@ -694,6 +699,7 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
pThis->m_aClients[ClientID].m_Authed = AUTHED_NO; pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
pThis->m_aClients[ClientID].m_AuthTries = 0; pThis->m_aClients[ClientID].m_AuthTries = 0;
pThis->m_aClients[ClientID].m_pRconCmdToSend = 0; pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
pThis->m_aClients[ClientID].m_pMapListEntryToSend = 0;
pThis->m_aClients[ClientID].m_NoRconNote = false; pThis->m_aClients[ClientID].m_NoRconNote = false;
pThis->m_aClients[ClientID].m_Quitting = false; pThis->m_aClients[ClientID].m_Quitting = false;
pThis->m_aClients[ClientID].m_Snapshots.PurgeAll(); pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();
@ -774,6 +780,36 @@ void CServer::UpdateClientRconCommands()
} }
} }
void CServer::SendMapListEntryAdd(const CMapListEntry *pMapListEntry, int ClientID)
{
CMsgPacker Msg(NETMSG_MAPLIST_ENTRY_ADD, true);
Msg.AddString(pMapListEntry->m_aName, 256);
SendMsg(&Msg, MSGFLAG_VITAL, ClientID);
}
void CServer::SendMapListEntryRem(const CMapListEntry *pMapListEntry, int ClientID)
{
CMsgPacker Msg(NETMSG_MAPLIST_ENTRY_REM, true);
Msg.AddString(pMapListEntry->m_aName, 256);
SendMsg(&Msg, MSGFLAG_VITAL, ClientID);
}
void CServer::UpdateClientMapListEntries()
{
for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MaxClients(); ClientID += MAX_RCONCMD_RATIO)
{
if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed)
{
for(int i = 0; i < MAX_MAPLISTENTRY_SEND && m_aClients[ClientID].m_pMapListEntryToSend; ++i)
{
SendMapListEntryAdd(m_aClients[ClientID].m_pMapListEntryToSend, ClientID);
m_aClients[ClientID].m_pMapListEntryToSend = m_aClients[ClientID].m_pMapListEntryToSend->m_pNext;
}
}
}
}
void CServer::ProcessClientPacket(CNetChunk *pPacket) void CServer::ProcessClientPacket(CNetChunk *pPacket)
{ {
int ClientID = pPacket->m_ClientID; int ClientID = pPacket->m_ClientID;
@ -979,6 +1015,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
m_aClients[ClientID].m_Authed = AUTHED_ADMIN; m_aClients[ClientID].m_Authed = AUTHED_ADMIN;
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER); m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER);
m_aClients[ClientID].m_pMapListEntryToSend = m_pFirstMapEntry;
SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted."); SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID);
@ -992,6 +1029,9 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
m_aClients[ClientID].m_Authed = AUTHED_MOD; m_aClients[ClientID].m_Authed = AUTHED_MOD;
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER); m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER);
SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted."); SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
const IConsole::CCommandInfo *pInfo = Console()->GetCommandInfo("sv_map", CFGFLAG_SERVER, false);
if(pInfo && pInfo->GetAccessLevel() == IConsole::ACCESS_LEVEL_MOD)
m_aClients[ClientID].m_pMapListEntryToSend = m_pFirstMapEntry;
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID); str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
@ -1232,6 +1272,13 @@ int CServer::Run()
// //
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this); m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
// list maps
m_pMapListHeap = new CHeap();
CSubdirCallbackUserdata Userdata;
Userdata.m_pServer = this;
str_copy(Userdata.m_aName, "", sizeof(Userdata.m_aName));
m_pStorage->ListDirectory(IStorage::TYPE_ALL, "maps/", MapListEntryCallback, &Userdata);
// load map // load map
if(!LoadMap(g_Config.m_SvMap)) if(!LoadMap(g_Config.m_SvMap))
{ {
@ -1361,6 +1408,7 @@ int CServer::Run()
DoSnapshot(); DoSnapshot();
UpdateClientRconCommands(); UpdateClientRconCommands();
UpdateClientMapListEntries();
} }
// master server stuff // master server stuff
@ -1414,6 +1462,52 @@ int CServer::Run()
return 0; return 0;
} }
int CServer::MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser)
{
CSubdirCallbackUserdata *pUserdata = (CSubdirCallbackUserdata *)pUser;
CServer *pThis = pUserdata->m_pServer;
if(pFilename[0] == '.') // hidden files
return 0;
char aFilename[512];
if(pUserdata->m_aName[0])
str_format(aFilename, sizeof(aFilename), "%s/%s", pUserdata->m_aName, pFilename);
else
str_format(aFilename, sizeof(aFilename), "%s", pFilename);
if(IsDir)
{
CSubdirCallbackUserdata Userdata;
Userdata.m_pServer = pThis;
str_copy(Userdata.m_aName, aFilename, sizeof(Userdata.m_aName));
char FindPath[512];
str_format(FindPath, sizeof(FindPath), "maps/%s/", aFilename);
pThis->m_pStorage->ListDirectory(IStorage::TYPE_ALL, FindPath, MapListEntryCallback, &Userdata);
return 0;
}
const char *pSuffix = str_endswith(aFilename, ".map");
if(!pSuffix) // not ending with .map
{
return 0;
}
CMapListEntry *pEntry = (CMapListEntry *)pThis->m_pMapListHeap->Allocate(sizeof(CMapListEntry));
pThis->m_NumMapEntries++;
pEntry->m_pNext = 0;
pEntry->m_pPrev = pThis->m_pLastMapEntry;
if(pEntry->m_pPrev)
pEntry->m_pPrev->m_pNext = pEntry;
pThis->m_pLastMapEntry = pEntry;
if(!pThis->m_pFirstMapEntry)
pThis->m_pFirstMapEntry = pEntry;
str_truncate(pEntry->m_aName, sizeof(pEntry->m_aName), aFilename, pSuffix-aFilename);
return 0;
}
void CServer::ConKick(IConsole::IResult *pResult, void *pUser) void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
{ {
if(pResult->NumArguments() > 1) if(pResult->NumArguments() > 1)
@ -1446,7 +1540,7 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
} }
else else
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr); str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr);
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
} }
} }
} }
@ -1518,6 +1612,7 @@ void CServer::ConLogout(IConsole::IResult *pResult, void *pUser)
pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO; pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0; pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0;
pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0; pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
pServer->m_aClients[pServer->m_RconClientID].m_pMapListEntryToSend = 0;
pServer->SendRconLine(pServer->m_RconClientID, "Logout successful."); pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
char aBuf[32]; char aBuf[32];
str_format(aBuf, sizeof(aBuf), "ClientID=%d logged out", pServer->m_RconClientID); str_format(aBuf, sizeof(aBuf), "ClientID=%d logged out", pServer->m_RconClientID);

View file

@ -4,7 +4,7 @@
#define ENGINE_SERVER_SERVER_H #define ENGINE_SERVER_SERVER_H
#include <engine/server.h> #include <engine/server.h>
#include <engine/shared/memheap.h>
class CSnapIDPool class CSnapIDPool
{ {
@ -76,9 +76,12 @@ public:
AUTHED_ADMIN, AUTHED_ADMIN,
MAX_RCONCMD_SEND=16, MAX_RCONCMD_SEND=16,
MAX_MAPLISTENTRY_SEND = 32,
MAX_RCONCMD_RATIO=8, MAX_RCONCMD_RATIO=8,
}; };
class CMapListEntry;
class CClient class CClient
{ {
public: public:
@ -128,6 +131,7 @@ public:
bool m_NoRconNote; bool m_NoRconNote;
bool m_Quitting; bool m_Quitting;
const IConsole::CCommandInfo *m_pRconCmdToSend; const IConsole::CCommandInfo *m_pRconCmdToSend;
const CMapListEntry *m_pMapListEntryToSend;
void Reset(); void Reset();
}; };
@ -163,6 +167,25 @@ public:
int m_CurrentMapSize; int m_CurrentMapSize;
int m_MapChunksPerRequest; int m_MapChunksPerRequest;
//maplist
struct CMapListEntry
{
CMapListEntry *m_pPrev;
CMapListEntry *m_pNext;
char m_aName[IConsole::TEMPMAP_NAME_LENGTH];
};
struct CSubdirCallbackUserdata
{
CServer *m_pServer;
char m_aName[IConsole::TEMPMAP_NAME_LENGTH];
};
CHeap *m_pMapListHeap;
CMapListEntry *m_pLastMapEntry;
CMapListEntry *m_pFirstMapEntry;
int m_NumMapEntries;
int m_RconPasswordSet; int m_RconPasswordSet;
int m_GeneratedRconPassword; int m_GeneratedRconPassword;
@ -214,6 +237,9 @@ public:
void SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID); void SendRconCmdAdd(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID); void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
void UpdateClientRconCommands(); void UpdateClientRconCommands();
void SendMapListEntryAdd(const CMapListEntry *pMapListEntry, int ClientID);
void SendMapListEntryRem(const CMapListEntry *pMapListEntry, int ClientID);
void UpdateClientMapListEntries();
void ProcessClientPacket(CNetChunk *pPacket); void ProcessClientPacket(CNetChunk *pPacket);
@ -228,6 +254,8 @@ public:
void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole); void InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterServer, IConsole *pConsole);
int Run(); int Run();
static int MapListEntryCallback(const char *pFilename, int IsDir, int DirType, void *pUser);
static void ConKick(IConsole::IResult *pResult, void *pUser); static void ConKick(IConsole::IResult *pResult, void *pUser);
static void ConStatus(IConsole::IResult *pResult, void *pUser); static void ConStatus(IConsole::IResult *pResult, void *pUser);
static void ConShutdown(IConsole::IResult *pResult, void *pUser); static void ConShutdown(IConsole::IResult *pResult, void *pUser);

View file

@ -356,6 +356,15 @@ void CConsole::PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPoss
} }
} }
void CConsole::PossibleMaps(const char *pStr, FPossibleCallback pfnCallback, void *pUser)
{
for(CMapListEntryTemp *pMapEntry = m_pFirstMapEntry; pMapEntry; pMapEntry = pMapEntry->m_pNext)
{
if(str_find_nocase(pMapEntry->m_aName, pStr))
pfnCallback(pMapEntry->m_aName, pUser);
}
}
CConsole::CCommand *CConsole::FindCommand(const char *pName, int FlagMask) CConsole::CCommand *CConsole::FindCommand(const char *pName, int FlagMask)
{ {
for(CCommand *pCommand = m_pFirstCommand; pCommand; pCommand = pCommand->m_pNext) for(CCommand *pCommand = m_pFirstCommand; pCommand; pCommand = pCommand->m_pNext)
@ -653,6 +662,10 @@ CConsole::CConsole(int FlagMask)
m_StoreCommands = true; m_StoreCommands = true;
m_paStrokeStr[0] = "0"; m_paStrokeStr[0] = "0";
m_paStrokeStr[1] = "1"; m_paStrokeStr[1] = "1";
m_pTempMapListHeap = 0;
m_NumMapListEntries = 0;
m_pFirstMapEntry = 0;
m_pLastMapEntry = 0;
m_ExecutionQueue.Reset(); m_ExecutionQueue.Reset();
m_pFirstCommand = 0; m_pFirstCommand = 0;
m_pFirstExec = 0; m_pFirstExec = 0;
@ -864,6 +877,71 @@ void CConsole::DeregisterTempAll()
m_pRecycleList = 0; m_pRecycleList = 0;
} }
void CConsole::RegisterTempMap(const char *pName)
{
if(!m_pTempMapListHeap)
m_pTempMapListHeap = new CHeap();
CMapListEntryTemp *pEntry = (CMapListEntryTemp *)m_pTempMapListHeap->Allocate(sizeof(CMapListEntryTemp));
pEntry->m_pNext = 0;
pEntry->m_pPrev = m_pLastMapEntry;
if(pEntry->m_pPrev)
pEntry->m_pPrev->m_pNext = pEntry;
m_pLastMapEntry = pEntry;
if(!m_pFirstMapEntry)
m_pFirstMapEntry = pEntry;
str_copy(pEntry->m_aName, pName, TEMPMAP_NAME_LENGTH);
m_NumMapListEntries++;
}
void CConsole::DeregisterTempMap(const char *pName)
{
CMapListEntryTemp *pEntry = m_pFirstMapEntry;
while(pEntry)
{
if(str_comp_nocase(pName, pEntry->m_aName) == 0)
break;
pEntry = pEntry->m_pNext;
}
m_NumMapListEntries--;
CHeap *pNewTempMapListHeap = new CHeap();
CMapListEntryTemp *pNewFirstEntry = 0;
CMapListEntryTemp *pNewLastEntry = 0;
int NewMapEntryNum = m_NumMapListEntries;
for(CMapListEntryTemp *pSrc = m_pFirstMapEntry; pSrc; pSrc = pSrc->m_pNext)
{
if(pSrc == pEntry)
continue;
CMapListEntryTemp *pDst = (CMapListEntryTemp *)pNewTempMapListHeap->Allocate(sizeof(CMapListEntryTemp));
pDst->m_pNext = 0;
pDst->m_pPrev = m_pLastMapEntry;
if(pDst->m_pPrev)
pDst->m_pPrev->m_pNext = pDst;
m_pLastMapEntry = pDst;
if(!m_pFirstMapEntry)
m_pFirstMapEntry = pDst;
str_copy(pDst->m_aName, pSrc->m_aName, TEMPMAP_NAME_LENGTH);
}
delete m_pTempMapListHeap;
m_pTempMapListHeap = pNewTempMapListHeap;
m_pFirstMapEntry = pNewFirstEntry;
m_pLastMapEntry = pNewLastEntry;
m_NumMapListEntries = NewMapEntryNum;
}
void CConsole::DeregisterTempMapAll()
{
m_pTempMapListHeap->Reset();
m_pFirstMapEntry = 0;
m_pLastMapEntry = 0;
m_NumMapListEntries = 0;
}
void CConsole::Con_Chain(IResult *pResult, void *pUserData) void CConsole::Con_Chain(IResult *pResult, void *pUserData)
{ {
CChain *pInfo = (CChain *)pUserData; CChain *pInfo = (CChain *)pUserData;

View file

@ -57,7 +57,7 @@ class CConsole : public IConsole
static void ConToggle(IResult *pResult, void *pUser); static void ConToggle(IResult *pResult, void *pUser);
static void ConToggleStroke(IResult *pResult, void *pUser); static void ConToggleStroke(IResult *pResult, void *pUser);
static void ConModCommandAccess(IResult *pResult, void *pUser); static void ConModCommandAccess(IResult *pResult, void *pUser);
static void ConModCommandStatus(IConsole::IResult *pResult, void *pUser); static void ConModCommandStatus(IResult *pResult, void *pUser);
void ExecuteFileRecurse(const char *pFilename); void ExecuteFileRecurse(const char *pFilename);
void ExecuteLineStroked(int Stroke, const char *pStr); void ExecuteLineStroked(int Stroke, const char *pStr);
@ -154,6 +154,17 @@ class CConsole : public IConsole
void AddCommandSorted(CCommand *pCommand); void AddCommandSorted(CCommand *pCommand);
CCommand *FindCommand(const char *pName, int FlagMask); CCommand *FindCommand(const char *pName, int FlagMask);
struct CMapListEntryTemp {
CMapListEntryTemp *m_pPrev;
CMapListEntryTemp *m_pNext;
char m_aName[TEMPMAP_NAME_LENGTH];
};
CHeap *m_pTempMapListHeap;
int m_NumMapListEntries;
CMapListEntryTemp *m_pFirstMapEntry;
CMapListEntryTemp *m_pLastMapEntry;
public: public:
CConsole(int FlagMask); CConsole(int FlagMask);
~CConsole(); ~CConsole();
@ -161,12 +172,16 @@ public:
virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int FlagMask) const; virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int FlagMask) const;
virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp); virtual const CCommandInfo *GetCommandInfo(const char *pName, int FlagMask, bool Temp);
virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser); virtual void PossibleCommands(const char *pStr, int FlagMask, bool Temp, FPossibleCallback pfnCallback, void *pUser);
virtual void PossibleMaps(const char *pStr, FPossibleCallback pfnCallback, void *pUser);
virtual void ParseArguments(int NumArgs, const char **ppArguments); 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 Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp);
virtual void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp); virtual void RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp);
virtual void DeregisterTemp(const char *pName); virtual void DeregisterTemp(const char *pName);
virtual void DeregisterTempAll(); virtual void DeregisterTempAll();
virtual void RegisterTempMap(const char *pName);
virtual void DeregisterTempMap(const char *pName);
virtual void DeregisterTempMapAll();
virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser); virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser);
virtual void StoreCommands(bool Store); virtual void StoreCommands(bool Store);

View file

@ -70,6 +70,9 @@ enum
NETMSG_PING, NETMSG_PING,
NETMSG_PING_REPLY, NETMSG_PING_REPLY,
NETMSG_ERROR, NETMSG_ERROR,
NETMSG_MAPLIST_ENTRY_ADD,// todo 0.8: move up
NETMSG_MAPLIST_ENTRY_REM,
}; };
// this should be revised // this should be revised

View file

@ -47,6 +47,9 @@ CGameConsole::CInstance::CInstance(int Type)
else else
m_CompletionFlagmask = CFGFLAG_SERVER; m_CompletionFlagmask = CFGFLAG_SERVER;
m_aCompletionMapBuffer[0] = 0;
m_CompletionMapChosen = -1;
m_aCompletionBuffer[0] = 0; m_aCompletionBuffer[0] = 0;
m_CompletionChosen = -1; m_CompletionChosen = -1;
m_CompletionRenderOffset = 0.0f; m_CompletionRenderOffset = 0.0f;
@ -93,6 +96,27 @@ void CGameConsole::CInstance::PossibleCommandsCompleteCallback(const char *pStr,
pInstance->m_CompletionEnumerationCount++; pInstance->m_CompletionEnumerationCount++;
} }
void CGameConsole::CInstance::PossibleMapsCompleteCallback(const char *pStr, void *pUser)
{
CGameConsole::CInstance *pInstance = (CGameConsole::CInstance *)pUser;
if(pInstance->m_CompletionMapChosen == pInstance->m_CompletionMapEnumerationCount)
{
// get command
char aBuf[512] = { 0 };
const char *pSrc = pInstance->GetString();
unsigned i = 0;
for(; i < sizeof(aBuf) - 2 && *pSrc && *pSrc != ' '; i++, pSrc++)
aBuf[i] = *pSrc;
aBuf[i++] = ' ';
aBuf[i] = 0;
// add mapname to current command
str_append(aBuf, pStr, sizeof(aBuf));
pInstance->m_Input.Set(aBuf);
}
pInstance->m_CompletionMapEnumerationCount++;
}
void CGameConsole::CInstance::OnInput(IInput::CEvent Event) void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
{ {
bool Handled = false; bool Handled = false;
@ -159,6 +183,22 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, m_Type != CGameConsole::CONSOLETYPE_LOCAL && m_pGameConsole->m_pConsole->PossibleCommands(m_aCompletionBuffer, m_CompletionFlagmask, m_Type != CGameConsole::CONSOLETYPE_LOCAL &&
m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands(), PossibleCommandsCompleteCallback, this); m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands(), PossibleCommandsCompleteCallback, this);
} }
// maplist completion
if(str_comp_nocase_num(GetString(), "sv_map ", 7) == 0 && m_Type != CGameConsole::CONSOLETYPE_LOCAL)
{
m_CompletionMapChosen++;
m_CompletionMapEnumerationCount = 0;
m_pGameConsole->m_pConsole->PossibleMaps(m_aCompletionMapBuffer, PossibleMapsCompleteCallback, this);
// handle wrapping
if(m_CompletionMapEnumerationCount && m_CompletionMapChosen >= m_CompletionMapEnumerationCount)
{
m_CompletionMapChosen %= m_CompletionMapEnumerationCount;
m_CompletionMapEnumerationCount = 0;
m_pGameConsole->m_pConsole->PossibleMaps(m_aCompletionMapBuffer, PossibleMapsCompleteCallback, this);
}
}
} }
} }
else if(Event.m_Key == KEY_PAGEUP) else if(Event.m_Key == KEY_PAGEUP)
@ -182,6 +222,12 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
{ {
m_CompletionChosen = -1; m_CompletionChosen = -1;
str_copy(m_aCompletionBuffer, m_Input.GetString(), sizeof(m_aCompletionBuffer)); str_copy(m_aCompletionBuffer, m_Input.GetString(), sizeof(m_aCompletionBuffer));
if(str_comp_nocase_num(GetString(), "sv_map ", 7) == 0)
{
m_CompletionMapChosen = -1;
str_copy(m_aCompletionMapBuffer, &m_Input.GetString()[7], sizeof(m_aCompletionBuffer));
}
} }
// find the current command // find the current command

View file

@ -23,15 +23,18 @@ class CGameConsole : public CComponent
CLineInput m_Input; CLineInput m_Input;
int m_Type; int m_Type;
int m_CompletionEnumerationCount;
int m_BacklogActPage; int m_BacklogActPage;
public:
CGameConsole *m_pGameConsole; CGameConsole *m_pGameConsole;
char m_aCompletionMapBuffer[128];
int m_CompletionMapChosen;
int m_CompletionMapEnumerationCount;
char m_aCompletionBuffer[128]; char m_aCompletionBuffer[128];
int m_CompletionChosen; int m_CompletionChosen;
int m_CompletionFlagmask; int m_CompletionFlagmask;
int m_CompletionEnumerationCount;
float m_CompletionRenderOffset; float m_CompletionRenderOffset;
bool m_IsCommand; bool m_IsCommand;
@ -52,6 +55,7 @@ class CGameConsole : public CComponent
const char *GetString() const { return m_Input.GetString(); } const char *GetString() const { return m_Input.GetString(); }
static void PossibleCommandsCompleteCallback(const char *pStr, void *pUser); static void PossibleCommandsCompleteCallback(const char *pStr, void *pUser);
static void PossibleMapsCompleteCallback(const char *pStr, void *pUser);
}; };
class IConsole *m_pConsole; class IConsole *m_pConsole;