3 #include "sourcemm_api.h"
4 #include "systems/LibrarySys.h"
5 #include "vm/sp_vm_engine.h"
10 #include "ExtensionSys.h"
12 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
14 SourcePawnEngine g_SourcePawn;
15 SourceModBase g_SourceMod;
17 ILibrary *g_pJIT = NULL;
18 SourceHook::String g_BaseDir;
19 ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
20 IVirtualMachine *g_pVM;
21 IdentityToken_t *g_pCoreIdent = NULL;
23 typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
24 typedef unsigned int (*GETEXPORTCOUNT)();
25 typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
26 typedef void (*NOTIFYSHUTDOWN)();
30 NOTIFYSHUTDOWN notify = (NOTIFYSHUTDOWN)g_pJIT->GetSymbolAddress("NotifyShutdown");
36 g_pJIT->CloseLibrary();
39 SourceModBase::SourceModBase()
41 m_IsMapLoading = false;
44 bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
46 g_BaseDir.assign(g_SMAPI->GetBaseDir());
47 g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
49 /* Attempt to load the JIT! */
50 char file[PLATFORM_MAX_PATH];
52 g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/sourcepawn.jit.x86.%s",
57 g_pJIT = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
62 snprintf(error, err_max, "%s (failed to load bin/sourcepawn.jit.x86.%s)",
70 GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
76 snprintf(error, err_max, "Failed to find GiveEnginePointer in JIT!");
81 if ((err=jit_init(g_pSourcePawn)) != 0)
86 snprintf(error, err_max, "GiveEnginePointer returned %d in the JIT", err);
91 GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
92 GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
98 snprintf(error, err_max, "JIT is missing a necessary export!");
103 unsigned int num = jit_getnum();
104 if (!num || ((g_pVM=jit_get(0)) == NULL))
107 if (error && err_max)
109 snprintf(error, err_max, "JIT did not export any virtual machines!");
114 unsigned int api = g_pVM->GetAPIVersion();
115 if (api != SOURCEPAWN_VM_API_VERSION)
118 if (error && err_max)
120 snprintf(error, err_max, "JIT is not a compatible version");
125 StartSourceMod(late);
130 void SourceModBase::StartSourceMod(bool late)
132 /* First initialize the global hooks we need */
133 SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
136 SMGlobalClass *pBase = SMGlobalClass::head;
139 pBase->OnSourceModStartup(false);
140 pBase = pBase->m_pGlobalClassNext;
143 /* Make the global core identity */
144 g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
147 pBase = SMGlobalClass::head;
150 pBase->OnSourceModAllInitialized();
151 pBase = pBase->m_pGlobalClassNext;
155 g_ShareSys.AddInterface(NULL, this);
158 bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
160 m_IsMapLoading = true;
162 g_Logger.MapChange(pMapName);
164 DoGlobalPluginLoads();
166 m_IsMapLoading = false;
168 RETURN_META_VALUE(MRES_IGNORED, true);
171 bool SourceModBase::IsMapLoading()
173 return m_IsMapLoading;
176 void SourceModBase::DoGlobalPluginLoads()
178 char config_path[PLATFORM_MAX_PATH];
179 char plugins_path[PLATFORM_MAX_PATH];
181 BuildPath(Path_SM, config_path,
183 "configs/plugin_settings.cfg");
184 BuildPath(Path_SM, plugins_path,
185 sizeof(plugins_path),
188 /* Run the first pass */
189 g_PluginSys.LoadAll_FirstPass(config_path, plugins_path);
191 /* Mark any extensions as loaded */
192 g_Extensions.MarkAllLoaded();
194 /* No modules yet, it's safe to call this from here */
195 g_PluginSys.LoadAll_SecondPass();
197 /* Re-mark any extensions as loaded */
198 g_Extensions.MarkAllLoaded();
201 size_t SourceModBase::BuildPath(PathType type, char *buffer, size_t maxlength, char *format, ...)
203 char _buffer[PLATFORM_MAX_PATH+1];
206 va_start(ap, format);
207 vsnprintf(_buffer, PLATFORM_MAX_PATH, format, ap);
210 const char *base = NULL;
211 if (type == Path_Game)
214 } else if (type == Path_SM) {
215 base = GetSourceModPath();
220 return g_LibSys.PathFormat(buffer, maxlength, "%s/%s", base, _buffer);
222 return g_LibSys.PathFormat(buffer, maxlength, "%s", _buffer);
226 void SourceModBase::CloseSourceMod()
229 SMGlobalClass *pBase = SMGlobalClass::head;
232 pBase->OnSourceModShutdown();
233 pBase = pBase->m_pGlobalClassNext;
237 pBase = SMGlobalClass::head;
240 pBase->OnSourceModAllShutdown();
241 pBase = pBase->m_pGlobalClassNext;
248 void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
250 IExtensionInterface *pAPI = pExt->GetAPI();
251 const char *tag = pAPI->GetExtensionTag();
255 va_start(ap, format);
256 vsnprintf(buffer, sizeof(buffer), format, ap);
261 g_Logger.LogMessage("[%s] %s", tag, buffer);
263 g_Logger.LogMessage("%s", buffer);
267 void SourceModBase::LogError(IExtension *pExt, const char *format, ...)
269 IExtensionInterface *pAPI = pExt->GetAPI();
270 const char *tag = pAPI->GetExtensionTag();
274 va_start(ap, format);
275 vsnprintf(buffer, sizeof(buffer), format, ap);
280 g_Logger.LogError("[%s] %s", tag, buffer);
282 g_Logger.LogError("%s", buffer);
286 const char *SourceModBase::GetSourceModPath()
291 const char *SourceModBase::GetModPath()
293 return g_BaseDir.c_str();
296 SMGlobalClass *SMGlobalClass::head = NULL;
298 SMGlobalClass::SMGlobalClass()
300 m_pGlobalClassNext = SMGlobalClass::head;
301 SMGlobalClass::head = this;