//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: defines a RCon class used to send rcon commands to remote servers // // $NoKeywords: $ //============================================================================= #include "mapslist.h" #include "Iresponse.h" #include "Socket.h" #include "proto_oob.h" #include "DialogGameInfo.h" #include "inetapi.h" #include "TokenLine.h" #include "dialogkickplayer.h" #include extern void v_strncpy(char *dest, const char *src, int bufsize); typedef enum { NONE = 0, INFO_REQUESTED, INFO_RECEIVED } RCONSTATUS; typedef enum { FS, PAK } MAP_TYPES; CMapsList::CMapsList(IResponse *target,serveritem_t &server, const char *rconPassword,const char *mod) { memcpy(&m_Server, &server,sizeof(serveritem_t)); m_pResponseTarget=target; if(strcmp(mod,"valve") ) { v_strncpy(m_sMod,mod,64); } else { m_sMod[0]=0; // its the "valve" default mod, list all maps } m_bIsRefreshing=false; m_bNewMapsList=false; m_bRconFailed=false; v_strncpy(m_szRconPassword,rconPassword,100); m_pRcon = new CRcon(this , server,rconPassword); } CMapsList::~CMapsList() { delete m_pRcon; } //----------------------------------------------------------------------------- // Purpose: sends a status query packet to a single server //----------------------------------------------------------------------------- void CMapsList::SendQuery() { m_bIsRefreshing=true; m_pRcon->SendRcon("maps *"); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapsList::RunFrame() { if(m_pRcon) { m_pRcon->RunFrame(); } } void CMapsList::ServerResponded() { char store[2048]; strcpy(store, m_pRcon->RconResponse()); char *cur=store; char *next=NULL; int i=0,k=0; bool checkDir=false; // maps format: // Dir: valve //------------- //(fs) rapidcore.bsp //(fs) frenzy.bsp //(fs) crossfire.bsp // //Dir: valve //------------- //(pak) boot_camp.bsp //(pak) bounce.bsp m_MapsList.RemoveAll(); char check[21]; _snprintf(check,21,"%s/",m_sMod); if(strstr(store,check)) { // if the name of the mod dir is in the return list its old style format checkDir=true; } while(cur!=NULL) { cur++; next=strchr(cur,'\n'); if(next!=NULL) { *next='\0'; } if( strncmp(cur,"Dir:",4) && strncmp(cur,"-------------",13) ) { TokenLine mapsLine; mapsLine.SetLine(cur); if(mapsLine.CountToken() >= 2 ) { char tmpMap[100]; v_strncpy(tmpMap,mapsLine.GetToken(1),100); // type char *end = strstr(tmpMap,".bsp"); // cull the .bsp if(end != NULL) { *end='\0'; } if(checkDir==true && strstr(tmpMap,m_sMod)==NULL ) // if the map name doesn't have the mod dir in it // and its not running the "valve" mod continue { cur=next; continue; } if ( strchr(tmpMap,'/') ) // remove the directory part of the map name { strcpy(tmpMap,strrchr(tmpMap,'/')+1); } for(k=0;k='1' && tmpMap[1]<='5')) // a heuristic to remove single player maps && !(tmpMap[0]=='t' && tmpMap[1]=='0') ) // from the list { Maps_t map; // this map wasn't found already v_strncpy(map.name,tmpMap,strlen(tmpMap)+1); if( !strcmp("(fs)",mapsLine.GetToken(0)) ) { // name map.type=FS; } else { map.type=PAK; } m_MapsList.AddToTail(map); i++; } // if k == Count } // CountToken } // if not a Dir: or "----------" cur=next; } m_bNewMapsList=true; m_bIsRefreshing=false; // notify the UI of the new server info m_pResponseTarget->ServerResponded(); } void CMapsList::ServerFailedToRespond() { // rcon failed //m_pResponseTarget->ServerFailedToRespond(); } void CMapsList::Refresh() { SendQuery(); } bool CMapsList::IsRefreshing() { return m_bIsRefreshing; } serveritem_t &CMapsList::GetServer() { return m_Server; } bool CMapsList::NewMapsList() { return m_bNewMapsList; } CUtlVector *CMapsList::GetMapsList() { m_bNewMapsList=false; return &m_MapsList; } void CMapsList::SetPassword(const char *newPass) { m_pRcon->SetPassword(newPass); m_bRconFailed=false; }