bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) { build_pathname_r(m_CurrentPath, sizeof(m_CurrentPath), "%s/gamedata/%s", get_localinfo("amxx_datadir", "addons/amxmodx/data"), file); m_IgnoreLevel = 0; m_ShouldBeReadingDefault = true; m_ParseState = PSTATE_NONE; SMCError err; SMCStates state = { 0, 0 }; if ((err = textparsers->ParseSMCFile(m_CurrentPath, this, &state, error, maxlength)) != SMCError_Okay) { const char *msg = textparsers->GetSMCErrorString(err); AMXXLOG_Error("Error parsing gameconfig file \"%s\":", m_CurrentPath); AMXXLOG_Error("Error %d on line %d, col %d: %s", err, state.line, state.col, msg ? msg : "Unknown error"); if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) { m_CustomHandler->ReadSMC_ParseEnd(true, true); m_CustomHandler = nullptr; m_CustomLevel = 0; } return false; } return true; }
void BuildPluginFileList(const char *initialdir, CStack<ke::AString *> & files) { char path[255]; #if defined WIN32 build_pathname_r(path, sizeof(path)-1, "%s/*.ini", initialdir); _finddata_t fd; intptr_t handle = _findfirst(path, &fd); if (handle < 0) { return; } while (!_findnext(handle, &fd)) { ParseAndOrAdd(files, fd.name); } _findclose(handle); #elif defined(__linux__) || defined(__APPLE__) build_pathname_r(path, sizeof(path)-1, "%s/", initialdir); struct dirent *ep; DIR *dp; if ((dp = opendir(path)) == NULL) { return; } while ( (ep=readdir(dp)) != NULL ) { ParseAndOrAdd(files, ep->d_name); } closedir (dp); #endif }
CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d , const char * shortName ) : name(n), title(n) { const char* unk = "unknown"; failcounter = 0; title.assign(unk); author.assign(unk); version.assign(unk); char file[256]; char* path = build_pathname_r(file, sizeof(file) - 1, "%s/%s", p, n); code = 0; memset(&amx, 0, sizeof(AMX)); int err = load_amxscript(&amx, &code, path, e, d , shortName ); if (err == AMX_ERR_NONE) { status = ps_running; } else { status = ps_bad_load; } amx.userdata[UD_FINDPLUGIN] = this; paused_fun = 0; next = 0; id = i; if (status == ps_running) { m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause", FP_DONE); m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause", FP_DONE); if (amx.flags & AMX_FLAG_DEBUG) { m_Debug = true; } else { m_Debug = false; } } }
CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, size_t m, int d) : name(n), title(n), m_pNullStringOfs(nullptr), m_pNullVectorOfs(nullptr) { const char* unk = "unknown"; failcounter = 0; title = unk; author = unk; version = unk; char file[PLATFORM_MAX_PATH]; char* path = build_pathname_r(file, sizeof(file), "%s/%s", p, n); code = 0; memset(&amx, 0, sizeof(AMX)); int err = load_amxscript_ex(&amx, &code, path, e, m, d); if (err == AMX_ERR_NONE) { status = ps_running; } else { status = ps_bad_load; } amx.userdata[UD_FINDPLUGIN] = this; paused_fun = 0; next = 0; id = i; if (status == ps_running) { m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause", FP_DONE); m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause", FP_DONE); if (amx.flags & AMX_FLAG_DEBUG) { m_Debug = true; } else { m_Debug = false; } } }
bool BinLog::Open() { const char *data = get_localinfo("amxmodx_datadir", "addons/amxmodx/data"); char path[255]; build_pathname_r(path, sizeof(path)-1, "%s/binlogs", data); if (!DirExists(path)) { mkdir(path #if defined(__linux__) || defined(__APPLE__) , 0755 #endif ); if (!DirExists(path)) return false; } char file[255]; build_pathname_r(file, sizeof(file)-1, "%s/binlogs/lastlog", data); unsigned int lastcntr = 0; FILE *lastlog = fopen(file, "rb"); if (lastlog) { if (fread(&lastcntr, sizeof(int), 1, lastlog) != 1) lastcntr = 0; fclose(lastlog); } lastlog = fopen(file, "wb"); if (lastlog) { lastcntr++; fwrite(&lastcntr, sizeof(int), 1, lastlog); fclose(lastlog); } build_pathname_r(file, sizeof(file)-1, "%s/binlogs/binlog%04d.blg", data, lastcntr); m_logfile = file; /** * it's now safe to create the binary log */ FILE *fp = fopen(m_logfile.chars(), "wb"); if (!fp) return false; int magic = BINLOG_MAGIC; short vers = BINLOG_VERSION; char c = sizeof(time_t); fwrite(&magic, sizeof(int), 1, fp); fwrite(&vers, sizeof(short), 1, fp); fwrite(&c, sizeof(char), 1, fp); WritePluginDB(fp); fclose(fp); m_state = true; WriteOp(BinLog_Start, -1); return true; }
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; }
void CPluginMngr::CALMFromFile(const char *file) { char filename[PLATFORM_MAX_PATH]; FILE *fp = fopen(build_pathname_r(filename, sizeof(filename), "%s", file), "rt"); if (!fp) { return; } // Find now folder char pluginName[256]; char line[256]; char rline[256]; while (!feof(fp)) { fgets(line, sizeof(line)-1, fp); if (line[0] == ';' || line[0] == '\n' || line[0] == '\0') { continue; } /** quick hack */ char *ptr = line; while (*ptr) { if (*ptr == ';') { *ptr = '\0'; } else { ptr++; } } strncopy(rline, line, sizeof(rline)); UTIL_TrimLeft(rline); UTIL_TrimRight(rline); pluginName[0] = '\0'; sscanf(rline, "%s", pluginName); /* HACK: see if there's a 'disabled' coming up * new block for scopying flexibility */ if (1) { const char *_ptr = rline + strlen(pluginName); while (*_ptr != '\0' && isspace(*_ptr)) { _ptr++; } if ((*_ptr != '\0') && !strcmp(_ptr, "disabled")) { ke::AString *pString = new ke::AString(pluginName); m_BlockList.push_back(pString); continue; } } if (!isalnum(*pluginName)) { continue; } build_pathname_r(filename, sizeof(filename), "%s/%s", get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"), pluginName); CacheAndLoadModules(filename); } fclose(fp); }
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) { char file[PLATFORM_MAX_PATH]; FILE *fp = fopen(build_pathname_r(file, sizeof(file), "%s", filename), "rt"); if (!fp) { if (warn) { AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename); } return 1; } // Find now folder char pluginName[256], error[256], debug[256]; int debugFlag = 0; const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); char line[512]; List<ke::AString *>::iterator block_iter; while (!feof(fp)) { pluginName[0] = '\0'; debug[0] = '\0'; debugFlag = 0; line[0] = '\0'; fgets(line, sizeof(line), fp); /** quick hack */ char *ptr = line; while (*ptr) { if (*ptr == ';') { *ptr = '\0'; } else { ptr++; } } sscanf(line, "%s %s", pluginName, debug); if (!isalnum(*pluginName)) { continue; } if (isalnum(*debug) && !strcmp(debug, "debug")) { debugFlag = 1; } bool skip = false; for (block_iter = m_BlockList.begin(); block_iter != m_BlockList.end(); block_iter++) { if ((*block_iter)->compare(pluginName) == 0) { skip = true; break; } } if (skip || !strcmp(debug, "disabled")) { continue; } if (findPlugin(pluginName) != NULL) { continue; } CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, sizeof(error), debugFlag); if (plugin->getStatusCode() == ps_bad_load) { char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } else { cell addr; if (amx_FindPubVar(plugin->getAMX(), "MaxClients", &addr) != AMX_ERR_NOTFOUND) { *get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients; } if (amx_FindPubVar(plugin->getAMX(), "MapName", &addr) != AMX_ERR_NOTFOUND) { set_amxstring(plugin->getAMX(), addr, STRING(gpGlobals->mapname), MAX_MAPNAME_LENGTH - 1); } if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND) { plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr); } if (amx_FindPubVar(plugin->getAMX(), "NULL_VECTOR", &addr) != AMX_ERR_NOTFOUND) { plugin->m_pNullVectorOfs = get_amxaddr(plugin->getAMX(), addr); } } } fclose(fp); return pCounter; }
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) { char file[256]; FILE *fp = fopen(build_pathname_r(file, sizeof(file) - 1, "%s", filename), "rt"); if (!fp) { if (warn) { AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename); } return 1; } // Find now folder char pluginName[256], error[256], debug[256]; int debugFlag = 0; const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); String line; List<String *>::iterator block_iter; while (!feof(fp)) { pluginName[0] = '\0'; debug[0] = '\0'; debugFlag = 0; line.clear(); line._fread(fp); /** quick hack */ char *ptr = const_cast<char *>(line.c_str()); while (*ptr) { if (*ptr == ';') { *ptr = '\0'; } else { ptr++; } } sscanf(line.c_str(), "%s %s", pluginName, debug); if (!isalnum(*pluginName)) { continue; } if (isalnum(*debug) && !strcmp(debug, "debug")) { debugFlag = 1; } bool skip = false; for (block_iter = m_BlockList.begin(); block_iter != m_BlockList.end(); block_iter++) { if ((*block_iter)->compare(pluginName) == 0) { skip = true; break; } } if (skip || !strcmp(debug, "disabled")) { continue; } if (findPlugin(pluginName) != NULL) { continue; } CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, debugFlag); if (plugin->getStatusCode() == ps_bad_load) { char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } fclose(fp); return pCounter; }
int CPluginMngr::loadPluginsFromDir(const char* dir, bool debug ){ char pluginName[ 256 ], error[ 256 ], dirFull[ 256 ]; char * ext = 0; #if defined WIN32 build_pathname_r( dirFull , sizeof( dirFull ) , "%s\\*" , dir ); _finddata_t fd; intptr_t handle = _findfirst( dirFull , &fd); if (handle < 0){ return 0; } while (!_findnext(handle, &fd)){ if ( !strcmp ( fd.name , ".") || !strcmp ( fd.name , "..") ){ continue; } ext = strrchr( fd.name, '.' ); if( !ext || strcmp( ext , ".amxx" ) ){ continue; } *ext = '\0'; strncpy( pluginName , fd.name , ext - ( fd.name ) ); pluginName[ ext - ( fd.name ) ] = '\0'; if ( findPlugin( pluginName ) != NULL ){ continue; } CPlugin* plugin = loadPlugin( dir, fd.name, error, debug , pluginName ); if (plugin->getStatusCode() == ps_bad_load){ char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } _findclose(handle); #elif defined(__linux__) || defined(__APPLE__) build_pathname_r( dirFull , sizeof( dirFull ) , "%s" , dir ); struct dirent *ep; DIR *dp; if (( dp = opendir( dirFull ) ) == NULL ){ return 0; } while ( ( ep = readdir( dp )) != NULL ){ if ( !strcmp ( ep -> d_name , ".") || !strcmp ( ep -> d_name , "..") ){ continue; } ext = strrchr( ep -> d_name, '.' ); if( !ext || strcmp( ext , ".amxx" ) ){ continue; } strncpy( pluginName , ep -> d_name , ext - ( ep -> d_name ) ); pluginName[ ext - ( ep -> d_name ) ] = '\0'; if ( findPlugin( pluginName ) != NULL ){ continue; } CPlugin* plugin = loadPlugin( dir, ep -> d_name, error, debug , pluginName ); if (plugin->getStatusCode() == ps_bad_load){ char errorMsg[255]; sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); plugin->setError(errorMsg); AMXXLOG_Error("[AMXX] %s", plugin->getError()); } } closedir (dp); #endif return pCounter; }
// Very first point at map load // Load AMX modules for new native functions // Initialize AMX stuff and load it's plugins from plugins.ini list // Call precache forward function from plugins int C_Spawn(edict_t *pent) { if (g_initialized) { RETURN_META_VALUE(MRES_IGNORED, 0); } g_activated = false; g_initialized = true; g_forcedmodules = false; g_forcedsounds = false; g_srvindex = IS_DEDICATED_SERVER() ? 0 : 1; hostname = CVAR_GET_POINTER("hostname"); mp_timelimit = CVAR_GET_POINTER("mp_timelimit"); // Fix for crashing on mods that do not have mp_timelimit if (mp_timelimit == NULL) { static cvar_t timelimit_holder; timelimit_holder.name = "mp_timelimit"; timelimit_holder.string = "0"; timelimit_holder.flags = 0; timelimit_holder.value = 0.0; CVAR_REGISTER(&timelimit_holder); mp_timelimit = &timelimit_holder; } g_forwards.clear(); g_log.MapChange(); // ###### Initialize task manager g_tasksMngr.registerTimers(&gpGlobals->time, &mp_timelimit->value, &g_game_timeleft); // ###### Initialize commands prefixes g_commands.registerPrefix("amx"); g_commands.registerPrefix("amxx"); g_commands.registerPrefix("say"); g_commands.registerPrefix("admin_"); g_commands.registerPrefix("sm_"); g_commands.registerPrefix("cm_"); // make sure localinfos are set get_localinfo("amxx_basedir", "addons/amxmodx"); get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"); get_localinfo("amxx_configsdir", "addons/amxmodx/configs"); get_localinfo("amxx_customdir", "addons/amxmodx/custom"); // make sure bcompat localinfos are set get_localinfo("amx_basedir", "addons/amxmodx"); get_localinfo("amx_configdir", "addons/amxmodx/configs"); get_localinfo("amx_langdir", "addons/amxmodx/data/amxmod-lang"); get_localinfo("amx_modulesdir", "addons/amxmodx/modules"); get_localinfo("amx_pluginsdir", "addons/amxmodx/plugins"); get_localinfo("amx_logdir", "addons/amxmodx/logs"); FlagMan.LoadFile(); ArrayHandles.clear(); TrieHandles.clear(); TrieSnapshotHandles.clear(); DataPackHandles.clear(); TextParsersHandles.clear(); GameConfigHandle.clear(); char map_pluginsfile_path[256]; char prefixed_map_pluginsfile[256]; char configs_dir[256]; // ###### Load modules loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini"), PT_ANYTIME); get_localinfo_r("amxx_configsdir", "addons/amxmodx/configs", configs_dir, sizeof(configs_dir)-1); g_plugins.CALMFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini")); LoadExtraPluginsToPCALM(configs_dir); char temporaryMap[64], *tmap_ptr; ke::SafeSprintf(temporaryMap, sizeof(temporaryMap), "%s", STRING(gpGlobals->mapname)); prefixed_map_pluginsfile[0] = '\0'; if ((tmap_ptr = strchr(temporaryMap, '_')) != NULL) { // this map has a prefix *tmap_ptr = '\0'; ke::SafeSprintf(prefixed_map_pluginsfile, sizeof(prefixed_map_pluginsfile), "%s/maps/plugins-%s.ini", configs_dir, temporaryMap); g_plugins.CALMFromFile(prefixed_map_pluginsfile); } ke::SafeSprintf(map_pluginsfile_path, sizeof(map_pluginsfile_path), "%s/maps/plugins-%s.ini", configs_dir, STRING(gpGlobals->mapname)); g_plugins.CALMFromFile(map_pluginsfile_path); int loaded = countModules(CountModules_Running); // Call after attachModules so all modules don't have pending stat // Set some info about amx version and modules CVAR_SET_STRING(init_amxmodx_version.name, AMXX_VERSION); char buffer[32]; sprintf(buffer, "%d", loaded); CVAR_SET_STRING(init_amxmodx_modules.name, buffer); // ###### Load Vault char file[255]; g_vault.setSource(build_pathname_r(file, sizeof(file) - 1, "%s", get_localinfo("amxx_vault", "addons/amxmodx/configs/vault.ini"))); g_vault.loadVault(); // ###### Init time and freeze tasks g_game_timeleft = g_bmod_dod ? 1.0f : 0.0f; g_task_time = gpGlobals->time + 99999.0f; g_auth_time = gpGlobals->time + 99999.0f; #ifdef MEMORY_TEST g_next_memreport_time = gpGlobals->time + 99999.0f; #endif g_players_num = 0; // Set server flags memset(g_players[0].flags, -1, sizeof(g_players[0].flags)); g_opt_level = atoi(get_localinfo("optimizer", "7")); if (!g_opt_level) g_opt_level = 7; // ###### Load AMX Mod X plugins g_plugins.loadPluginsFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini")); LoadExtraPluginsFromDir(configs_dir); g_plugins.loadPluginsFromFile(map_pluginsfile_path, false); if (prefixed_map_pluginsfile[0] != '\0') { g_plugins.loadPluginsFromFile(prefixed_map_pluginsfile, false); } g_plugins.Finalize(); g_plugins.InvalidateCache(); // Register forwards FF_PluginInit = registerForward("plugin_init", ET_IGNORE, FP_DONE); FF_ClientCommand = registerForward("client_command", ET_STOP, FP_CELL, FP_DONE); FF_ClientConnect = registerForward("client_connect", ET_IGNORE, FP_CELL, FP_DONE); FF_ClientDisconnect = registerForward("client_disconnect", ET_IGNORE, FP_CELL, FP_DONE); FF_ClientDisconnected = registerForward("client_disconnected", ET_IGNORE, FP_CELL, FP_CELL, FP_ARRAY, FP_CELL, FP_DONE); FF_ClientRemove = registerForward("client_remove", ET_IGNORE, FP_CELL, FP_CELL, FP_STRING, FP_DONE); FF_ClientInfoChanged = registerForward("client_infochanged", ET_IGNORE, FP_CELL, FP_DONE); FF_ClientPutInServer = registerForward("client_putinserver", ET_IGNORE, FP_CELL, FP_DONE); FF_PluginCfg = registerForward("plugin_cfg", ET_IGNORE, FP_DONE); FF_PluginPrecache = registerForward("plugin_precache", ET_IGNORE, FP_DONE); FF_PluginLog = registerForward("plugin_log", ET_STOP, FP_DONE); FF_PluginEnd = registerForward("plugin_end", ET_IGNORE, FP_DONE); FF_InconsistentFile = registerForward("inconsistent_file", ET_STOP, FP_CELL, FP_STRING, FP_STRINGEX, FP_DONE); FF_ClientAuthorized = registerForward("client_authorized", ET_IGNORE, FP_CELL, FP_STRING, FP_DONE); FF_ChangeLevel = registerForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE); FF_ClientConnectEx = registerForward("client_connectex", ET_STOP, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE); CoreCfg.OnAmxxInitialized(); #if defined BINLOG_ENABLED if (!g_BinLog.Open()) { LOG_ERROR(PLID, "Binary log failed to open."); } g_binlog_level = atoi(get_localinfo("bin_logging", "17")); g_binlog_maxsize = atoi(get_localinfo("max_binlog_size", "20")); #endif modules_callPluginsLoaded(); TypeConversion.init(); // ###### Call precache forward function g_dontprecache = false; executeForwards(FF_PluginPrecache); g_dontprecache = true; for (CList<ForceObject>::iterator a = g_forcegeneric.begin(); a; ++a) { PRECACHE_GENERIC((char*)(*a).getFilename()); ENGINE_FORCE_UNMODIFIED((*a).getForceType(), (*a).getMin(), (*a).getMax(), (*a).getFilename()); } RETURN_META_VALUE(MRES_IGNORED, 0); }