core/sourcemod.cpp
author David Anderson <dvander@alliedmods.net>
Fri Dec 15 13:58:22 2006 +0000 (2006-12-15)
changeset 214 4d97709c9376
parent 213 2bec1ff85d06
child 252 ce166c465bad
permissions -rw-r--r--
added global class initializers
     1 #include <stdio.h>
     2 #include "sourcemod.h"
     3 #include "sourcemm_api.h"
     4 #include "systems/LibrarySys.h"
     5 #include "vm/sp_vm_engine.h"
     6 #include <sh_string.h>
     7 #include "PluginSys.h"
     8 #include "ForwardSys.h"
     9 
    10 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
    11 
    12 SourcePawnEngine g_SourcePawn;
    13 SourceModBase g_SourceMod;
    14 
    15 ILibrary *g_pJIT = NULL;
    16 SourceHook::String g_BaseDir;
    17 ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
    18 IVirtualMachine *g_pVM;
    19 
    20 typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
    21 typedef unsigned int (*GETEXPORTCOUNT)();
    22 typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
    23 typedef void (*NOTIFYSHUTDOWN)();
    24 
    25 void ShutdownJIT()
    26 {
    27 	NOTIFYSHUTDOWN notify = (NOTIFYSHUTDOWN)g_pJIT->GetSymbolAddress("NotifyShutdown");
    28 	if (notify)
    29 	{
    30 		notify();
    31 	}
    32 
    33 	g_pJIT->CloseLibrary();
    34 }
    35 
    36 SourceModBase::SourceModBase()
    37 {
    38 	m_IsMapLoading = false;
    39 }
    40 
    41 bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
    42 {
    43 	g_BaseDir.assign(g_SMAPI->GetBaseDir());
    44 	g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
    45 
    46 	/* Attempt to load the JIT! */
    47 	char file[PLATFORM_MAX_PATH];
    48 	char myerror[255];
    49 	g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/sourcepawn.jit.x86.%s",
    50 		GetSMBaseDir(),
    51 		PLATFORM_LIB_EXT
    52 		);
    53 
    54 	g_pJIT = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
    55 	if (!g_pJIT)
    56 	{
    57 		if (error && err_max)
    58 		{
    59 			snprintf(error, err_max, "%s (failed to load bin/sourcepawn.jit.x86.%s)", 
    60 				myerror,
    61 				PLATFORM_LIB_EXT);
    62 		}
    63 		return false;
    64 	}
    65 
    66 	int err;
    67 	GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
    68 	if (!jit_init)
    69 	{
    70 		ShutdownJIT();
    71 		if (error && err_max)
    72 		{
    73 			snprintf(error, err_max, "Failed to find GiveEnginePointer in JIT!");
    74 		}
    75 		return false;
    76 	}
    77 
    78 	if ((err=jit_init(g_pSourcePawn)) != 0)
    79 	{
    80 		ShutdownJIT();
    81 		if (error && err_max)
    82 		{
    83 			snprintf(error, err_max, "GiveEnginePointer returned %d in the JIT", err);
    84 		}
    85 		return false;
    86 	}
    87 
    88 	GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
    89 	GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
    90 	if (!jit_get)
    91 	{
    92 		ShutdownJIT();
    93 		if (error && err_max)
    94 		{
    95 			snprintf(error, err_max, "JIT is missing a necessary export!");
    96 		}
    97 		return false;
    98 	}
    99 
   100 	unsigned int num = jit_getnum();
   101 	if (!num || ((g_pVM=jit_get(0)) == NULL))
   102 	{
   103 		ShutdownJIT();
   104 		if (error && err_max)
   105 		{
   106 			snprintf(error, err_max, "JIT did not export any virtual machines!");
   107 		}
   108 		return false;
   109 	}
   110 
   111 	unsigned int api = g_pVM->GetAPIVersion();
   112 	if (api != SOURCEPAWN_VM_API_VERSION)
   113 	{
   114 		ShutdownJIT();
   115 		if (error && err_max)
   116 		{
   117 			snprintf(error, err_max, "JIT is not a compatible version");
   118 		}
   119 		return false;
   120 	}
   121 
   122 	StartSourceMod(late);
   123 
   124 	return true;
   125 }
   126 
   127 void SourceModBase::StartSourceMod(bool late)
   128 {
   129 	/* First initialize the global hooks we need */
   130 	SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
   131 
   132 	m_IsLateLoadInMap = late;
   133 
   134 	/* Notify! */
   135 	SMGlobalClass *pBase = SMGlobalClass::head;
   136 	while (pBase)
   137 	{
   138 		pBase->OnSourceModStartup(m_IsLateLoadInMap);
   139 		pBase = pBase->m_pGlobalClassNext;
   140 	}
   141 
   142 	/* Notify! */
   143 	pBase = SMGlobalClass::head;
   144 	while (pBase)
   145 	{
   146 		pBase->OnSourceModAllInitialized();
   147 		pBase = pBase->m_pGlobalClassNext;
   148 	}
   149 
   150 	/* If we're late, automatically load plugins now */
   151 	if (late)
   152 	{
   153 		DoGlobalPluginLoads();
   154 	}
   155 }
   156 
   157 bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
   158 {
   159 	m_IsMapLoading = true;
   160 	m_IsLateLoadInMap = false;
   161 
   162 	DoGlobalPluginLoads();
   163 
   164 	m_IsMapLoading = false;
   165 
   166 	RETURN_META_VALUE(MRES_IGNORED, true);
   167 }
   168 
   169 void SourceModBase::DoGlobalPluginLoads()
   170 {
   171 	char config_path[PLATFORM_MAX_PATH];
   172 	char plugins_path[PLATFORM_MAX_PATH];
   173 
   174 	g_SMAPI->PathFormat(config_path, 
   175 		sizeof(config_path),
   176 		"%s/configs/plugin_settings.cfg",
   177 		GetSMBaseDir());
   178 	g_SMAPI->PathFormat(plugins_path,
   179 		sizeof(plugins_path),
   180 		"%s/plugins",
   181 		GetSMBaseDir());
   182 
   183 	g_PluginSys.LoadAll_FirstPass(config_path, plugins_path);
   184 
   185 	/* No modules yet, it's safe to call this from here */
   186 	g_PluginSys.LoadAll_SecondPass();
   187 }
   188 
   189 bool SourceModBase::IsLateLoadInMap()
   190 {
   191 	return m_IsLateLoadInMap;
   192 }
   193 
   194 const char *SourceModBase::GetSMBaseDir()
   195 {
   196 	return m_SMBaseDir;
   197 }
   198 
   199 SMGlobalClass *SMGlobalClass::head = NULL;
   200 
   201 SMGlobalClass::SMGlobalClass()
   202 {
   203 	m_pGlobalClassNext = SMGlobalClass::head;
   204 	SMGlobalClass::head = this;
   205 }