From 6847c8eec054d04024a71336caf69d09aecde3c3 Mon Sep 17 00:00:00 2001 From: Ryan Stecker Date: Wed, 3 Jul 2013 23:23:05 -0400 Subject: [PATCH] Fixed ReadMapList not seeing maps in all valveFS paths (bug 5715, r=asherkin). --- core/logic/intercom.h | 18 ++++++++++- core/logic/smn_maplists.cpp | 59 +++++++++++++++---------------------- core/logic/stringutil.cpp | 32 ++++++++++++++++++++ core/logic/stringutil.h | 2 ++ core/logic_bridge.cpp | 20 +++++++++++++ core/sourcemm_api.cpp | 2 ++ core/sourcemm_api.h | 1 + 7 files changed, 98 insertions(+), 36 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index d2c968d0..0dc5347f 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -42,7 +42,7 @@ using namespace SourceMod; * Add 1 to the RHS of this expression to bump the intercom file * This is to prevent mismatching core/logic binaries */ -#define SM_LOGIC_MAGIC (0x0F47C0DE - 17) +#define SM_LOGIC_MAGIC (0x0F47C0DE - 18) #if defined SM_LOGIC class IVEngineServer @@ -55,6 +55,20 @@ public: virtual void ServerCommand(const char *cmd) = 0; }; +typedef int FileFindHandle_t; + +#if defined SM_LOGIC +class IFileSystem +#else +class IFileSystem_Logic +#endif +{ +public: + virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0; + virtual const char *FindNext(FileFindHandle_t handle) = 0; + virtual void FindClose(FileFindHandle_t handle) = 0; +}; + namespace SourceMod { class ISourceMod; @@ -74,6 +88,7 @@ namespace SourceMod } class IVEngineServer; +class IFileSystem; class ConVar; struct ServerGlobals @@ -91,6 +106,7 @@ struct sm_core_t ISourceMod *sm; ILibrarySys *libsys; IVEngineServer *engine; + IFileSystem *filesystem; IShareSys *sharesys; IRootConsole *rootmenu; IPluginManager *pluginsys; diff --git a/core/logic/smn_maplists.cpp b/core/logic/smn_maplists.cpp index 92795248..edfb9cd7 100644 --- a/core/logic/smn_maplists.cpp +++ b/core/logic/smn_maplists.cpp @@ -37,6 +37,7 @@ #include #include #include +#include "stringutil.h" using namespace SourceHook; @@ -349,51 +350,39 @@ public: if ((success && pNewArray == NULL) || (!success && ((flags & MAPLIST_FLAG_MAPSFOLDER) == MAPLIST_FLAG_MAPSFOLDER))) { - char path[255]; - IDirectory *pDir; - pNewArray = new CellArray(64); free_new_array = true; - g_pSM->BuildPath(Path_Game, path, sizeof(path), "maps"); - if ((pDir = libsys->OpenDirectory(path)) != NULL) + cell_t *blk; + + FileFindHandle_t findHandle; + const char *fileName = smcore.filesystem->FindFirstEx("maps/*.bsp", "GAME", &findHandle); + + while (fileName) { - char *ptr; - cell_t *blk; char buffer[PLATFORM_MAX_PATH]; - while (pDir->MoreFiles()) + UTIL_StripExtension(fileName, buffer, sizeof(buffer)); + + if (!engine->IsMapValid(buffer)) { - if (!pDir->IsEntryFile() - || strcmp(pDir->GetEntryName(), ".") == 0 - || strcmp(pDir->GetEntryName(), "..") == 0) - { - pDir->NextEntry(); - continue; - } - smcore.strncopy(buffer, pDir->GetEntryName(), sizeof(buffer)); - if ((ptr = strstr(buffer, ".bsp")) == NULL || ptr[4] != '\0') - { - pDir->NextEntry(); - continue; - } - *ptr = '\0'; - if (!engine->IsMapValid(buffer)) - { - pDir->NextEntry(); - continue; - } - if ((blk = pNewArray->push()) == NULL) - { - pDir->NextEntry(); - continue; - } - smcore.strncopy((char *)blk, buffer, 255); - pDir->NextEntry(); + fileName = smcore.filesystem->FindNext(findHandle); + continue; } - libsys->CloseDirectory(pDir); + + if ((blk = pNewArray->push()) == NULL) + { + fileName = smcore.filesystem->FindNext(findHandle); + continue; + } + + smcore.strncopy((char *)blk, buffer, 255); + + fileName = smcore.filesystem->FindNext(findHandle); } + smcore.filesystem->FindClose(findHandle); + /* Remove the array if there were no items. */ if (pNewArray->size() == 0) { diff --git a/core/logic/stringutil.cpp b/core/logic/stringutil.cpp index d6ca9294..3d8b92e7 100644 --- a/core/logic/stringutil.cpp +++ b/core/logic/stringutil.cpp @@ -303,3 +303,35 @@ size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char return written; } +#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') + +void UTIL_StripExtension(const char *in, char *out, int outSize) +{ + // Find the last dot. If it's followed by a dot or a slash, then it's part of a + // directory specifier like ../../somedir/./blah. + + // scan backward for '.' + int end = strlen(in) - 1; + while (end > 0 && in[end] != '.' && !PATHSEPARATOR(in[end])) + { + --end; + } + + if (end > 0 && !PATHSEPARATOR(in[end]) && end < outSize) + { + int nChars = min(end, outSize-1); + if (out != in) + { + memcpy(out, in, nChars); + } + out[nChars] = 0; + } + else + { + // nothing found + if (out != in) + { + strncopy(out, in, outSize); + } + } +} diff --git a/core/logic/stringutil.h b/core/logic/stringutil.h index 6ff04641..f4296965 100644 --- a/core/logic/stringutil.h +++ b/core/logic/stringutil.h @@ -40,5 +40,7 @@ char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t se const char *replace, size_t replaceLen, bool caseSensitive = true); size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr); +void UTIL_StripExtension(const char *in, char *out, int outSize); + #endif /* _INCLUDE_SOURCEMOD_COMMON_STRINGUTIL_H_ */ diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index bb4a10ba..bd3642fe 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -90,6 +90,25 @@ public: static VEngineServer_Logic logic_engine; +class VFileSystem_Logic : public IFileSystem_Logic +{ +public: + const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) + { + return filesystem->FindFirstEx(pWildCard, pPathID, pHandle); + } + const char *FindNext(FileFindHandle_t handle) + { + return filesystem->FindNext(handle); + } + void FindClose(FileFindHandle_t handle) + { + filesystem->FindClose(handle); + } +}; + +static VFileSystem_Logic logic_filesystem; + static void add_natives(sp_nativeinfo_t *natives) { g_pCoreNatives->AddNatives(natives); @@ -200,6 +219,7 @@ static sm_core_t core_bridge = &g_SourceMod, &g_LibSys, reinterpret_cast(&logic_engine), + reinterpret_cast(&logic_filesystem), &g_ShareSys, &g_RootMenu, &g_PluginSys, diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index 6a3b74d1..5818b267 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -50,6 +50,7 @@ CallClass *enginePatch = NULL; CallClass *gamedllPatch = NULL; IPlayerInfoManager *playerinfo = NULL; IBaseFileSystem *basefilesystem = NULL; +IFileSystem *filesystem = NULL; IEngineSound *enginesound = NULL; IServerPluginHelpers *serverpluginhelpers = NULL; IServerPluginCallbacks *vsp_interface = NULL; @@ -68,6 +69,7 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); GET_V_IFACE_CURRENT(GetEngineFactory, engrandom, IUniformRandomStream, VENGINE_SERVER_RANDOM_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetFileSystemFactory, basefilesystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION); + GET_V_IFACE_CURRENT(GetFileSystemFactory, filesystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, enginesound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, serverpluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index 60b09937..7b0fcf8a 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -99,6 +99,7 @@ extern SourceHook::CallClass *gamedllPatch; extern IUniformRandomStream *engrandom; extern IPlayerInfoManager *playerinfo; extern IBaseFileSystem *basefilesystem; +extern IFileSystem *filesystem; extern IEngineSound *enginesound; extern IServerPluginHelpers *serverpluginhelpers; extern IServerPluginCallbacks *vsp_interface;