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