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