bool CGameConfig::Reparse(char *error, size_t maxlength) { m_Offsets.clear(); m_OffsetsByClass.clear(); m_Keys.clear(); m_Addresses.clear(); char path[PLATFORM_MAX_PATH]; const char *dataDir = get_localinfo("amxx_datadir", "addons/amxmodx/data"); build_pathname_r(path, sizeof(path), "%s/gamedata/%s/master.games.txt", dataDir, m_File); if (!g_LibSys.PathExists(path)) { // Single config file without master g_LibSys.PathFormat(path, sizeof(path), "%s.txt", m_File); if (!EnterFile(path, error, maxlength)) { return false; } // Allow customizations of default gamedata files build_pathname_r(path, sizeof(path), "%s/gamedata/custom/%s.txt", dataDir, m_File); if (g_LibSys.PathExists(path)) { g_LibSys.PathFormat(path, sizeof(path), "custom/%s.txt", m_File); auto success = EnterFile(path, error, maxlength); if (success) { AMXXLOG_Log("[AMXX] Parsed custom gamedata override file: %s", path); } return success; } return true; } SMCError err; SMCStates state = { 0, 0 }; ke::Vector<ke::AString> fileList; MasterReader.m_FileList = &fileList; err = textparsers->ParseSMCFile(path, &MasterReader, &state, error, maxlength); if (err != SMCError_Okay) { const char *msg = textparsers->GetSMCErrorString(err); AMXXLOG_Error("Error parsing master gameconf file \"%s\":", path); AMXXLOG_Error("Error %d on line %d, col %d: %s", err, state.line, state.col, msg ? msg : "Unknown error"); return false; } for (size_t i = 0; i < fileList.length(); ++i) { g_LibSys.PathFormat(path, sizeof(path), "%s/%s", m_File, fileList[i].chars()); if (!EnterFile(path, error, maxlength)) { return false; } } build_pathname_r(path, sizeof(path), "%s/gamedata/%s/custom", dataDir, m_File); CDirectory *customDir = g_LibSys.OpenDirectory(path); if (!customDir) { return true; } while (customDir->MoreFiles()) { if (!customDir->IsEntryFile()) { customDir->NextEntry(); continue; } const char *currentFile = customDir->GetEntryName(); size_t length = strlen(currentFile); if (length > 4 && strcmp(¤tFile[length - 4], ".txt") != 0) { customDir->NextEntry(); continue; } g_LibSys.PathFormat(path, sizeof(path), "%s/custom/%s", m_File, currentFile); if (!EnterFile(path, error, maxlength)) { g_LibSys.CloseDirectory(customDir); return false; } AMXXLOG_Log("[AMXX] Parsed custom gamedata override file: %s", path); customDir->NextEntry(); } g_LibSys.CloseDirectory(customDir); return true; }
// native next_file(dirh, buffer[], length, &FileType:type = FileType_Unknown); static cell AMX_NATIVE_CALL amx_get_dir(AMX *amx, cell *params) { DirectoryHandle* p = reinterpret_cast<DirectoryHandle*>(params[1]); if (!p) { return 0; } size_t numParams = *params / sizeof(cell); if (p->valvefs) { FileFindHandle_t* handle = reinterpret_cast<FileFindHandle_t*>(p->handle); if (!handle) { return 0; } const char* entry = g_FileSystem->FindNext(*handle); if (!entry) { return 0; } if (numParams >= 4) { cell* fileType = get_amxaddr(amx, params[4]); *fileType = g_FileSystem->FindIsDirectory(*handle) ? FileType_Directory : FileType_File; } set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3] + 1); } else { CDirectory* handle = reinterpret_cast<CDirectory*>(p->handle); if (!handle) { return 0; } handle->NextEntry(); if (!handle->MoreFiles()) { return 0; } if (numParams >= 4) { cell* fileType = get_amxaddr(amx, params[4]); *fileType = handle->IsEntryDirectory() ? FileType_Directory : FileType_File; } const char* entry = handle->GetEntryName(); set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3] + 1); } return 1; }