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