dvander@370: /**
ds@653: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
dvander@1231: * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@370: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1231: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1231: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1231: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@370: *
dvander@370: * Version: $Id$
dvander@370: */
dvander@370:
dvander@160: #include
dvander@160: #include "sourcemod.h"
dvander@160: #include "sourcemm_api.h"
dvander@160: #include "systems/LibrarySys.h"
dvander@160: #include "vm/sp_vm_engine.h"
dvander@160: #include
dvander@176: #include "PluginSys.h"
dvander@252: #include "ShareSys.h"
ds@661: #include "CoreConfig.h"
dvander@592: #include "Logger.h"
dvander@315: #include "ExtensionSys.h"
dvander@340: #include "AdminCache.h"
dvander@347: #include "sm_stringutil.h"
dvander@591: #include "PlayerManager.h"
dvander@591: #include "Translator.h"
dvander@531: #include "ForwardSys.h"
faluco@593: #include "TimerSys.h"
dvander@1380: #include "GameConfigs.h"
dvander@160:
dvander@209: SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
faluco@333: SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
dvander@448: SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
dvander@978: SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
dvander@209:
dvander@160: SourcePawnEngine g_SourcePawn;
dvander@160: SourceModBase g_SourceMod;
dvander@160:
dvander@160: ILibrary *g_pJIT = NULL;
dvander@160: SourceHook::String g_BaseDir;
dvander@160: ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
dvander@160: IVirtualMachine *g_pVM;
dvander@252: IdentityToken_t *g_pCoreIdent = NULL;
dvander@718: IForward *g_pOnMapEnd = NULL;
dvander@688: bool g_Loaded = false;
dvander@160:
dvander@160: typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
dvander@1147: typedef int (*GIVEENGINEPOINTER2)(ISourcePawnEngine *, unsigned int api_version);
dvander@160: typedef unsigned int (*GETEXPORTCOUNT)();
dvander@160: typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
dvander@160: typedef void (*NOTIFYSHUTDOWN)();
dvander@160:
dvander@160: void ShutdownJIT()
dvander@160: {
dvander@160: NOTIFYSHUTDOWN notify = (NOTIFYSHUTDOWN)g_pJIT->GetSymbolAddress("NotifyShutdown");
dvander@160: if (notify)
dvander@160: {
dvander@160: notify();
dvander@160: }
dvander@160:
dvander@160: g_pJIT->CloseLibrary();
dvander@160: }
dvander@160:
dvander@209: SourceModBase::SourceModBase()
dvander@209: {
dvander@209: m_IsMapLoading = false;
faluco@333: m_ExecPluginReload = false;
ds@661: m_GotBasePath = false;
ds@661: }
ds@661:
dvander@663: ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key,
dvander@663: const char *value,
dvander@663: ConfigSource source,
dvander@663: char *error,
dvander@663: size_t maxlength)
ds@661: {
dvander@665: if (strcasecmp(key, "BasePath") == 0)
ds@661: {
dvander@663: if (source == ConfigSource_Console)
dvander@663: {
dvander@663: UTIL_Format(error, maxlength, "Cannot be set at runtime");
dvander@663: return ConfigResult_Reject;
dvander@663: }
dvander@663:
ds@661: if (!m_GotBasePath)
ds@661: {
ds@661: g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), value);
ds@661: g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), value);
ds@661:
ds@661: m_GotBasePath = true;
dvander@663: }
ds@661:
dvander@663: return ConfigResult_Accept;
ds@661: }
ds@661:
dvander@663: return ConfigResult_Ignore;
dvander@209: }
dvander@209:
ds@755: bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late)
dvander@160: {
ds@696: const char *gamepath = g_SMAPI->GetBaseDir();
ds@696:
ds@696: /* Store full path to game */
ds@696: g_BaseDir.assign(gamepath);
ds@696:
ds@696: /* Store name of game directory by itself */
ds@696: size_t len = strlen(gamepath);
ds@696: for (size_t i = len - 1; i >= 0; i--)
ds@696: {
ds@696: if (gamepath[i] == PLATFORM_SEP_CHAR)
ds@696: {
ds@696: strncopy(m_ModDir, &gamepath[++i], sizeof(m_ModDir));
ds@696: break;
ds@696: }
ds@696: }
ds@661:
ds@661: /* Initialize CoreConfig so we can get SourceMod base path properly - this basically parses core.cfg */
ds@661: g_CoreConfig.Initialize();
ds@661:
ds@661: /* This shouldn't happen, but can't hurt to be safe */
dvander@663: if (!g_LibSys.PathExists(m_SMBaseDir) || !m_GotBasePath)
ds@661: {
ds@661: g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
ds@661: g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod");
ds@661: m_GotBasePath = true;
ds@661: }
dvander@160:
dvander@160: /* Attempt to load the JIT! */
dvander@160: char file[PLATFORM_MAX_PATH];
dvander@160: char myerror[255];
dvander@209: g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/sourcepawn.jit.x86.%s",
dvander@317: GetSourceModPath(),
dvander@160: PLATFORM_LIB_EXT
dvander@160: );
dvander@160:
dvander@160: g_pJIT = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
dvander@160: if (!g_pJIT)
dvander@160: {
ds@755: if (error && maxlength)
dvander@160: {
ds@755: snprintf(error, maxlength, "%s (failed to load bin/sourcepawn.jit.x86.%s)",
dvander@160: myerror,
dvander@160: PLATFORM_LIB_EXT);
dvander@160: }
dvander@160: return false;
dvander@160: }
dvander@160:
dvander@160: int err;
dvander@1147:
dvander@1147: GIVEENGINEPOINTER2 jit_init2 = (GIVEENGINEPOINTER2)g_pJIT->GetSymbolAddress("GiveEnginePointer2");
dvander@1147: if (!jit_init2)
dvander@160: {
dvander@1147: GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
dvander@1147: if (!jit_init)
dvander@160: {
dvander@1147: ShutdownJIT();
dvander@1147: if (error && maxlength)
dvander@1147: {
dvander@1147: snprintf(error, maxlength, "Failed to find GiveEnginePointer in JIT!");
dvander@1147: }
dvander@1147: return false;
dvander@160: }
dvander@160:
dvander@1147: if ((err=jit_init(g_pSourcePawn)) != 0)
dvander@160: {
dvander@1147: ShutdownJIT();
dvander@1147: if (error && maxlength)
dvander@1147: {
dvander@1147: snprintf(error, maxlength, "GiveEnginePointer returned %d in the JIT", err);
dvander@1147: }
dvander@1147: return false;
dvander@160: }
dvander@1147: } else {
dvander@1147: /* On version bumps, we should check for older versions as well, if the new version fails.
dvander@1147: * We can then check the exports to see if any VM versions will be sufficient.
dvander@1147: */
dvander@1147: if ((err=jit_init2(g_pSourcePawn, SOURCEPAWN_ENGINE_API_VERSION)) != SP_ERROR_NONE)
dvander@1147: {
dvander@1147: ShutdownJIT();
dvander@1147: if (error && maxlength)
dvander@1147: {
dvander@1147: snprintf(error, maxlength, "JIT incompatible with SourceMod version");
dvander@1147: }
dvander@1147: return false;
dvander@1147: }
dvander@160: }
dvander@160:
dvander@160: GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
dvander@160: GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
dvander@160: if (!jit_get)
dvander@160: {
dvander@160: ShutdownJIT();
ds@755: if (error && maxlength)
dvander@160: {
ds@755: snprintf(error, maxlength, "JIT is missing a necessary export!");
dvander@160: }
dvander@160: return false;
dvander@160: }
dvander@160:
dvander@160: unsigned int num = jit_getnum();
dvander@1147: if (!num)
dvander@160: {
dvander@160: ShutdownJIT();
ds@755: if (error && maxlength)
dvander@160: {
ds@755: snprintf(error, maxlength, "JIT did not export any virtual machines!");
dvander@160: }
dvander@160: return false;
dvander@160: }
dvander@160:
dvander@1147: unsigned int api_version;
dvander@1147: for (unsigned int i=0; iGetAPIVersion();
dvander@1147: if (api_version < 3 || api_version > SOURCEPAWN_VM_API_VERSION)
dvander@1147: {
dvander@1147: if (error && maxlength)
dvander@1147: {
dvander@1147: snprintf(error, maxlength, "JIT is not a compatible version");
dvander@1147: }
dvander@1147: g_pVM = NULL;
dvander@1147: continue;
dvander@1147: }
dvander@1147: break;
dvander@1147: }
dvander@1147:
dvander@1147: if (!g_pVM)
dvander@176: {
dvander@176: ShutdownJIT();
dvander@176: return false;
dvander@176: }
dvander@176:
dvander@688: /* Hook this now so we can detect startup without calling StartSourceMod() */
dvander@688: SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
dvander@688:
dvander@688: /* Only load if we're not late */
dvander@688: if (!late)
dvander@688: {
dvander@688: StartSourceMod(false);
dvander@688: }
dvander@176:
dvander@160: return true;
dvander@160: }
dvander@209:
dvander@209: void SourceModBase::StartSourceMod(bool late)
dvander@209: {
faluco@333: SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false);
dvander@1412: SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, &g_Timers, &TimerSystem::GameFrame, false);
dvander@209:
dvander@496: enginePatch = SH_GET_CALLCLASS(engine);
dvander@532: gamedllPatch = SH_GET_CALLCLASS(gamedll);
dvander@496:
dvander@1770: g_ShareSys.Initialize();
dvander@1770:
dvander@1770: /* Make the global core identity */
dvander@1770: g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
dvander@1770:
dvander@214: /* Notify! */
dvander@214: SMGlobalClass *pBase = SMGlobalClass::head;
dvander@214: while (pBase)
dvander@214: {
dvander@315: pBase->OnSourceModStartup(false);
dvander@214: pBase = pBase->m_pGlobalClassNext;
dvander@214: }
dvander@214:
dvander@214: /* Notify! */
dvander@214: pBase = SMGlobalClass::head;
dvander@214: while (pBase)
dvander@214: {
dvander@214: pBase->OnSourceModAllInitialized();
dvander@214: pBase = pBase->m_pGlobalClassNext;
dvander@214: }
dvander@317:
dvander@317: /* Add us now... */
dvander@317: g_ShareSys.AddInterface(NULL, this);
dvander@688:
dvander@688: /* We're loaded! */
dvander@688: g_Loaded = true;
dvander@1581:
dvander@1581: /* Initialize VSP stuff */
dvander@1581: if (vsp_interface != NULL)
dvander@1581: {
dvander@1581: g_SourceMod_Core.OnVSPListening(vsp_interface);
dvander@1581: }
dvander@209: }
dvander@209:
dvander@916: static bool g_LevelEndBarrier = false;
dvander@209: bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
dvander@209: {
dvander@688: /* If we're not loaded... */
dvander@688: if (!g_Loaded)
dvander@688: {
dvander@688: /* Do all global initialization now */
dvander@688: StartSourceMod(true);
dvander@688: }
dvander@688:
dvander@209: m_IsMapLoading = true;
faluco@333: m_ExecPluginReload = true;
dvander@209:
dvander@673: /* Notify! */
dvander@673: SMGlobalClass *pBase = SMGlobalClass::head;
dvander@673: while (pBase)
dvander@673: {
dvander@673: pBase->OnSourceModLevelChange(pMapName);
dvander@673: pBase = pBase->m_pGlobalClassNext;
dvander@673: }
dvander@520:
dvander@209: DoGlobalPluginLoads();
dvander@209:
dvander@209: m_IsMapLoading = false;
dvander@209:
dvander@673: /* Notify! */
dvander@673: pBase = SMGlobalClass::head;
dvander@673: while (pBase)
dvander@673: {
dvander@673: pBase->OnSourceModPluginsLoaded();
dvander@673: pBase = pBase->m_pGlobalClassNext;
dvander@673: }
dvander@340:
dvander@718: if (!g_pOnMapEnd)
dvander@718: {
dvander@718: g_pOnMapEnd = g_Forwards.CreateForward("OnMapEnd", ET_Ignore, 0, NULL);
dvander@718: }
dvander@718:
dvander@916: g_LevelEndBarrier = true;
dvander@916:
dvander@209: RETURN_META_VALUE(MRES_IGNORED, true);
dvander@209: }
dvander@209:
faluco@333: void SourceModBase::LevelShutdown()
faluco@333: {
dvander@916: if (g_LevelEndBarrier)
dvander@916: {
dvander@916: SMGlobalClass *next = SMGlobalClass::head;
dvander@916: while (next)
dvander@916: {
dvander@916: next->OnSourceModLevelEnd();
dvander@916: next = next->m_pGlobalClassNext;
dvander@916: }
dvander@1721:
dvander@1721: if (g_pOnMapEnd != NULL)
dvander@1721: {
dvander@1721: g_pOnMapEnd->Execute(NULL);
dvander@1721: }
dvander@916:
dvander@1721: g_Timers.RemoveMapChangeTimers();
dvander@1721:
dvander@1721: g_LevelEndBarrier = false;
dvander@718: }
dvander@718:
dvander@848: g_OnMapStarted = false;
dvander@848:
faluco@333: if (m_ExecPluginReload)
faluco@333: {
faluco@333: g_PluginSys.ReloadOrUnloadPlugins();
faluco@333: m_ExecPluginReload = false;
faluco@333: }
faluco@333: }
faluco@333:
faluco@484: bool SourceModBase::IsMapLoading() const
dvander@315: {
dvander@315: return m_IsMapLoading;
dvander@315: }
dvander@315:
dvander@209: void SourceModBase::DoGlobalPluginLoads()
dvander@209: {
dvander@209: char config_path[PLATFORM_MAX_PATH];
dvander@209: char plugins_path[PLATFORM_MAX_PATH];
dvander@209:
dvander@317: BuildPath(Path_SM, config_path,
dvander@209: sizeof(config_path),
dvander@317: "configs/plugin_settings.cfg");
dvander@317: BuildPath(Path_SM, plugins_path,
dvander@209: sizeof(plugins_path),
dvander@317: "plugins");
dvander@209:
dvander@397: /* Load any auto extensions */
dvander@397: g_Extensions.TryAutoload();
dvander@397:
dvander@1655: /* Fire the extensions ready message */
dvander@1655: g_SMAPI->MetaFactory(SOURCEMOD_NOTICE_EXTENSIONS, NULL, NULL);
dvander@1655:
dvander@1380: /* Load any game extension */
dvander@1380: const char *game_ext;
dvander@1380: if ((game_ext = g_pGameConf->GetKeyValue("GameExtension")) != NULL)
dvander@1380: {
dvander@1380: char path[PLATFORM_MAX_PATH];
dvander@1568: UTIL_Format(path, sizeof(path), "%s.ext." PLATFORM_LIB_EXT, game_ext);
dvander@1456: g_Extensions.LoadAutoExtension(path);
dvander@1380: }
dvander@1380:
dvander@315: /* Run the first pass */
dvander@211: g_PluginSys.LoadAll_FirstPass(config_path, plugins_path);
dvander@213:
dvander@315: /* Mark any extensions as loaded */
dvander@315: g_Extensions.MarkAllLoaded();
dvander@315:
dvander@213: /* No modules yet, it's safe to call this from here */
dvander@213: g_PluginSys.LoadAll_SecondPass();
dvander@315:
dvander@315: /* Re-mark any extensions as loaded */
dvander@315: g_Extensions.MarkAllLoaded();
faluco@1221:
faluco@1221: /* Call OnAllPluginsLoaded */
faluco@1221: g_PluginSys.AllPluginsLoaded();
dvander@211: }
dvander@211:
ds@1411: size_t SourceModBase::BuildPath(PathType type, char *buffer, size_t maxlength, const char *format, ...)
dvander@317: {
ds@652: char _buffer[PLATFORM_MAX_PATH];
dvander@317: va_list ap;
dvander@317:
dvander@317: va_start(ap, format);
dvander@317: vsnprintf(_buffer, PLATFORM_MAX_PATH, format, ap);
dvander@317: va_end(ap);
dvander@317:
dvander@1729: /* If we get a "file://" notation, strip off the file:// part so we're left
dvander@1729: * with an absolute path. Note that the absolute path gets returned, so
dvander@1729: * usage with relative paths here is completely invalid.
dvander@1729: */
dvander@1729: if (type != Path_SM_Rel && strncmp(_buffer, "file://", 7) == 0)
dvander@1729: {
dvander@1729: return g_LibSys.PathFormat(buffer, maxlength, "%s", &_buffer[7]);
dvander@1729: }
dvander@1729:
dvander@317: const char *base = NULL;
dvander@317: if (type == Path_Game)
dvander@317: {
ds@729: base = GetGamePath();
dvander@1729: }
dvander@1729: else if (type == Path_SM)
dvander@1729: {
dvander@317: base = GetSourceModPath();
dvander@1729: }
dvander@1729: else if (type == Path_SM_Rel)
dvander@1729: {
dvander@345: base = m_SMRelDir;
dvander@317: }
dvander@317:
dvander@317: if (base)
dvander@317: {
dvander@317: return g_LibSys.PathFormat(buffer, maxlength, "%s/%s", base, _buffer);
dvander@1729: }
dvander@1729: else
dvander@1729: {
dvander@317: return g_LibSys.PathFormat(buffer, maxlength, "%s", _buffer);
dvander@317: }
dvander@317: }
dvander@317:
faluco@289: void SourceModBase::CloseSourceMod()
faluco@289: {
dvander@1018: /* Force a level end */
dvander@1018: LevelShutdown();
dvander@1018:
dvander@1018: /* Unload plugins */
dvander@1018: g_PluginSys.Shutdown();
dvander@1018:
dvander@1018: /* Unload extensions */
dvander@1018: g_Extensions.Shutdown();
dvander@1018:
dvander@688: SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
faluco@484:
dvander@688: if (g_Loaded)
dvander@496: {
dvander@718: if (g_pOnMapEnd)
dvander@718: {
dvander@718: g_Forwards.ReleaseForward(g_pOnMapEnd);
dvander@718: }
dvander@688:
dvander@688: /* Notify! */
dvander@688: SMGlobalClass *pBase = SMGlobalClass::head;
dvander@688: while (pBase)
dvander@688: {
dvander@688: pBase->OnSourceModShutdown();
dvander@688: pBase = pBase->m_pGlobalClassNext;
dvander@688: }
dvander@688:
dvander@688: /* Delete all data packs */
dvander@688: CStack::iterator iter;
dvander@688: CDataPack *pd;
dvander@688: for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
dvander@688: {
dvander@688: pd = (*iter);
dvander@688: delete pd;
dvander@688: }
dvander@688: m_freepacks.popall();
dvander@688:
dvander@688: /* Notify! */
dvander@688: pBase = SMGlobalClass::head;
dvander@688: while (pBase)
dvander@688: {
dvander@688: pBase->OnSourceModAllShutdown();
dvander@688: pBase = pBase->m_pGlobalClassNext;
dvander@688: }
dvander@688:
dvander@688: if (enginePatch)
dvander@688: {
dvander@688: SH_RELEASE_CALLCLASS(enginePatch);
dvander@688: enginePatch = NULL;
dvander@688: }
dvander@688:
dvander@688: if (gamedllPatch)
dvander@688: {
dvander@688: SH_RELEASE_CALLCLASS(gamedllPatch);
dvander@688: gamedllPatch = NULL;
dvander@688: }
dvander@496:
dvander@688: SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false);
dvander@1412: SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, &g_Timers, &TimerSystem::GameFrame, false);
dvander@532: }
dvander@532:
faluco@289: /* Rest In Peace */
faluco@289: ShutdownJIT();
faluco@289: }
faluco@289:
dvander@317: void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
dvander@317: {
dvander@317: IExtensionInterface *pAPI = pExt->GetAPI();
dvander@317: const char *tag = pAPI->GetExtensionTag();
dvander@317: char buffer[2048];
dvander@317: va_list ap;
dvander@317:
dvander@317: va_start(ap, format);
dvander@317: vsnprintf(buffer, sizeof(buffer), format, ap);
dvander@317: va_end(ap);
dvander@317:
dvander@317: if (tag)
dvander@317: {
dvander@317: g_Logger.LogMessage("[%s] %s", tag, buffer);
dvander@317: } else {
dvander@317: g_Logger.LogMessage("%s", buffer);
dvander@317: }
dvander@317: }
dvander@317:
dvander@317: void SourceModBase::LogError(IExtension *pExt, const char *format, ...)
dvander@317: {
dvander@317: IExtensionInterface *pAPI = pExt->GetAPI();
dvander@317: const char *tag = pAPI->GetExtensionTag();
dvander@317: char buffer[2048];
dvander@317: va_list ap;
dvander@317:
dvander@317: va_start(ap, format);
dvander@317: vsnprintf(buffer, sizeof(buffer), format, ap);
dvander@317: va_end(ap);
dvander@317:
dvander@317: if (tag)
dvander@317: {
dvander@317: g_Logger.LogError("[%s] %s", tag, buffer);
dvander@317: } else {
dvander@317: g_Logger.LogError("%s", buffer);
dvander@317: }
dvander@317: }
dvander@317:
dvander@347: size_t SourceModBase::FormatString(char *buffer, size_t maxlength, IPluginContext *pContext, const cell_t *params, unsigned int param)
dvander@347: {
dvander@347: char *fmt;
dvander@347:
dvander@347: pContext->LocalToString(params[param], &fmt);
dvander@347:
dvander@347: int lparam = ++param;
dvander@347:
dvander@347: return atcprintf(buffer, maxlength, fmt, pContext, params, &lparam);
dvander@347: }
dvander@347:
faluco@484: const char *SourceModBase::GetSourceModPath() const
dvander@209: {
dvander@209: return m_SMBaseDir;
dvander@209: }
dvander@211:
ds@729: const char *SourceModBase::GetGamePath() const
dvander@255: {
dvander@255: return g_BaseDir.c_str();
dvander@255: }
dvander@255:
dvander@1690: unsigned int SourceModBase::SetGlobalTarget(unsigned int index)
faluco@422: {
dvander@1690: unsigned int old = m_target;
faluco@422: m_target = index;
dvander@1690: return old;
faluco@422: }
faluco@422:
faluco@422: unsigned int SourceModBase::GetGlobalTarget() const
faluco@422: {
faluco@422: return m_target;
faluco@422: }
faluco@422:
faluco@484: IDataPack *SourceModBase::CreateDataPack()
faluco@484: {
faluco@484: CDataPack *pack;
faluco@484: if (m_freepacks.empty())
faluco@484: {
faluco@484: pack = new CDataPack;
faluco@484: } else {
faluco@484: pack = m_freepacks.front();
faluco@484: m_freepacks.pop();
faluco@484: pack->Initialize();
faluco@484: }
faluco@484: return pack;
faluco@484: }
faluco@484:
faluco@484: void SourceModBase::FreeDataPack(IDataPack *pack)
faluco@484: {
faluco@484: m_freepacks.push(static_cast(pack));
faluco@484: }
faluco@484:
faluco@484: Handle_t SourceModBase::GetDataPackHandleType(bool readonly)
faluco@484: {
faluco@484: //:TODO:
faluco@484: return 0;
faluco@484: }
faluco@484:
ds@729: const char *SourceModBase::GetGameFolderName() const
ds@696: {
ds@696: return m_ModDir;
ds@696: }
ds@696:
faluco@733: ISourcePawnEngine *SourceModBase::GetScriptingEngine()
faluco@733: {
faluco@733: return g_pSourcePawn;
faluco@733: }
faluco@733:
faluco@733: IVirtualMachine *SourceModBase::GetScriptingVM()
faluco@733: {
faluco@733: return g_pVM;
faluco@733: }
faluco@733:
dvander@893: void SourceModBase::AllPluginsLoaded()
dvander@893: {
dvander@893: SMGlobalClass *base = SMGlobalClass::head;
dvander@893: while (base)
dvander@893: {
dvander@893: base->OnSourceModGameInitialized();
dvander@893: base = base->m_pGlobalClassNext;
dvander@893: }
dvander@893: }
dvander@893:
dvander@1371: time_t SourceModBase::GetAdjustedTime()
dvander@1371: {
dvander@1371: return GetAdjustedTime();
dvander@1371: }
dvander@1371:
dvander@211: SMGlobalClass *SMGlobalClass::head = NULL;
dvander@211:
dvander@211: SMGlobalClass::SMGlobalClass()
dvander@211: {
dvander@211: m_pGlobalClassNext = SMGlobalClass::head;
dvander@211: SMGlobalClass::head = this;
dvander@211: }