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