core/smn_core.cpp
author Michael McKoy <ferret99gt@gmail.com>
Wed Aug 08 23:26:42 2007 +0000 (2007-08-08)
changeset 1280 13c62962a9ef
parent 1231 17badaf66ce4
child 1330 ab94316bb52b
permissions -rw-r--r--
Corrected filename in header of basefuncommands.sp
     1 /**
     2  * vim: set ts=4 :
     3  * ================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * ================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or 
     9  * modify it under the terms of the GNU General Public License, 
    10  * version 3.0, as published by the Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to 
    21  * link the code of this program (as well as its derivative works) to 
    22  * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
    23  * Game MODs that run on software by the Valve Corporation.  You must 
    24  * obey the GNU General Public License in all respects for all other 
    25  * code used. Additionally, AlliedModders LLC grants this exception 
    26  * to all derivative works. AlliedModders LLC defines further 
    27  * exceptions, found in LICENSE.txt (as of this writing, version 
    28  * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32 
    33 #include <time.h>
    34 #include <string.h>
    35 #include "sm_stringutil.h"
    36 #include "sm_globals.h"
    37 #include "sourcemod.h"
    38 #include "PluginSys.h"
    39 #include "HandleSys.h"
    40 #include "LibrarySys.h"
    41 
    42 #if defined PLATFORM_WINDOWS
    43 #include <windows.h>
    44 #elif defined PLATFORM_LINUX
    45 #include <limits.h>
    46 #include <unistd.h>
    47 #include <sys/times.h>
    48 #endif
    49 
    50 HandleType_t g_PlIter;
    51 
    52 class CoreNativeHelpers : 
    53 	public SMGlobalClass,
    54 	public IHandleTypeDispatch
    55 {
    56 public:
    57 	void OnSourceModAllInitialized()
    58 	{
    59 		HandleAccess hacc;
    60 		g_HandleSys.InitAccessDefaults(NULL,  &hacc);
    61 		hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
    62 
    63 		g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    64 	}
    65 	void OnHandleDestroy(HandleType_t type, void *object)
    66 	{
    67 		IPluginIterator *iter = (IPluginIterator *)object;
    68 		iter->Release();
    69 	}
    70 	void OnSourceModShutdown()
    71 	{
    72 		g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent);
    73 	}
    74 } g_CoreNativeHelpers;
    75 
    76 
    77 static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
    78 {
    79 	char buffer[512];
    80 
    81 	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    82 
    83 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
    84 
    85 	if (pContext->GetContext()->n_err == SP_ERROR_NONE)
    86 	{
    87 		pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
    88 	}
    89 
    90 	return 0;
    91 }
    92 
    93 static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
    94 {
    95 	time_t t = time(NULL);
    96 	cell_t *addr;
    97 	pContext->LocalToPhysAddr(params[1], &addr);
    98 
    99 	*(time_t *)addr = t;
   100 
   101 	return static_cast<cell_t>(t);
   102 }
   103 
   104 static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
   105 {
   106 	char *format, *buffer;
   107 	pContext->LocalToString(params[1], &buffer);
   108 	pContext->LocalToString(params[3], &format);
   109 
   110 	time_t t = (params[4] == -1) ? time(NULL) : (time_t)params[4];
   111 	strftime(buffer, params[2], format, localtime(&t));
   112 
   113 	return 1;
   114 }
   115 
   116 static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
   117 {
   118 	IPluginIterator *iter = g_PluginSys.GetPluginIterator();
   119 
   120 	Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
   121 
   122 	if (hndl == BAD_HANDLE)
   123 	{
   124 		iter->Release();
   125 	}
   126 
   127 	return hndl;
   128 }
   129 
   130 static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
   131 {
   132 	Handle_t hndl = (Handle_t)params[1];
   133 	HandleError err;
   134 	IPluginIterator *pIter;
   135 
   136 	HandleSecurity sec;
   137 	sec.pIdentity = g_pCoreIdent;
   138 	sec.pOwner = pContext->GetIdentity();
   139 
   140 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   141 	{
   142 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   143 	}
   144 
   145 	return pIter->MorePlugins() ? 1 : 0;
   146 }
   147 
   148 static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
   149 {
   150 	Handle_t hndl = (Handle_t)params[1];
   151 	HandleError err;
   152 	IPluginIterator *pIter;
   153 
   154 	HandleSecurity sec;
   155 	sec.pIdentity = g_pCoreIdent;
   156 	sec.pOwner = pContext->GetIdentity();
   157 
   158 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   159 	{
   160 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   161 	}
   162 
   163 	CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin();
   164 	if (!pPlugin)
   165 	{
   166 		return BAD_HANDLE;
   167 	}
   168 
   169 	pIter->NextPlugin();
   170 
   171 	return pPlugin->GetMyHandle();
   172 }
   173 
   174 CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
   175 {
   176 	if (hndl == BAD_HANDLE)
   177 	{
   178 		return g_PluginSys.GetPluginByCtx(pContext->GetContext());
   179 	} else {
   180 		HandleError err;
   181 		CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err);
   182 		if (!pPlugin)
   183 		{
   184 			pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   185 		}
   186 		return pPlugin;
   187 	}
   188 }
   189 
   190 static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
   191 {
   192 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   193 	if (!pPlugin)
   194 	{
   195 		return 0;
   196 	}
   197 
   198 	return pPlugin->GetStatus();
   199 }
   200 
   201 static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
   202 {
   203 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   204 	if (!pPlugin)
   205 	{
   206 		return 0;
   207 	}
   208 
   209 	pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
   210 
   211 	return 1;
   212 }
   213 
   214 static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
   215 {
   216 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   217 	if (!pPlugin)
   218 	{
   219 		return 0;
   220 	}
   221 
   222 	return pPlugin->IsDebugging() ? 1 : 0;
   223 }
   224 
   225 /* Local to plugins only */
   226 enum PluginInfo
   227 {
   228 	PlInfo_Name,			/**< Plugin name */
   229 	PlInfo_Author,			/**< Plugin author */
   230 	PlInfo_Description,		/**< Plugin description */
   231 	PlInfo_Version,			/**< Plugin verison */
   232 	PlInfo_URL,				/**< Plugin URL */
   233 };
   234 
   235 static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
   236 {
   237 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   238 	if (!pPlugin)
   239 	{
   240 		return 0;
   241 	}
   242 
   243 	const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
   244 
   245 	if (!info)
   246 	{
   247 		return 0;
   248 	}
   249 
   250 	const char *str = NULL;
   251 
   252 	switch ((PluginInfo)params[2])
   253 	{
   254 	case PlInfo_Name:
   255 		{
   256 			str = info->name;
   257 			break;
   258 		}
   259 	case PlInfo_Author:
   260 		{
   261 			str = info->author;
   262 			break;
   263 		}
   264 	case PlInfo_Description:
   265 		{
   266 			str = info->description;
   267 			break;
   268 		}
   269 	case PlInfo_Version:
   270 		{
   271 			str = info->version;
   272 			break;
   273 		}
   274 	case PlInfo_URL:
   275 		{
   276 			str = info->url;
   277 			break;
   278 		}
   279 	}
   280 
   281 	if (!str || str[0] == '\0')
   282 	{
   283 		return 0;
   284 	}
   285 
   286 	pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
   287 
   288 	return 1;
   289 }
   290 
   291 static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
   292 {
   293 	char *str;
   294 	pContext->LocalToString(params[1], &str);
   295 
   296 	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   297 	pPlugin->SetErrorState(Plugin_Error, "%s", str);
   298 
   299 	return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
   300 }
   301 
   302 static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
   303 {
   304 #if defined PLATFORM_WINDOWS
   305 	return (cell_t)GetTickCount();
   306 #elif defined PLATFORM_LINUX
   307 	tms tm;
   308 	clock_t ticks = times(&tm);
   309 	long ticks_per_sec = sysconf(_SC_CLK_TCK);
   310 	double fticks = (double)ticks / (double)ticks_per_sec;
   311 	fticks *= 1000.0f;
   312 	if (fticks > INT_MAX)
   313 	{
   314 		double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
   315 		fticks -= r;
   316 	}
   317 	return (cell_t)fticks;
   318 #endif
   319 }
   320 
   321 static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
   322 {
   323 	CPlugin *plugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   324 
   325 	char *cfg, *folder;
   326 	pContext->LocalToString(params[2], &cfg);
   327 	pContext->LocalToString(params[3], &folder);
   328 
   329 	if (cfg[0] == '\0')
   330 	{
   331 		static char temp_str[255];
   332 		static char temp_file[PLATFORM_MAX_PATH];
   333 		char *ptr;
   334 
   335 		g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
   336 		if ((ptr = strstr(temp_str, ".smx")) != NULL)
   337 		{
   338 			*ptr = '\0';
   339 		}
   340 
   341 		/* We have the raw filename! */
   342 		UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
   343 		cfg = temp_file;
   344 	}
   345 
   346 	plugin->AddConfig(params[1] ? true : false, cfg, folder);
   347 
   348 	return 1;
   349 }
   350 
   351 static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *params)
   352 {
   353 	char *name;
   354 	uint32_t idx;
   355 	sp_context_t *ctx = pContext->GetContext();
   356 
   357 	pContext->LocalToString(params[1], &name);
   358 	if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
   359 	{
   360 		/* Oops! This HAS to silently fail! */
   361 		return 0;
   362 	}
   363 
   364 	ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL;
   365 
   366 	return 1;
   367 }
   368 
   369 static cell_t RegPluginLibrary(IPluginContext *pContext, const cell_t *params)
   370 {
   371 	char *name;
   372 	CPlugin *pl = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   373 
   374 	pContext->LocalToString(params[1], &name);
   375 
   376 	pl->AddLibrary(name);
   377 
   378 	return 1;
   379 }
   380 
   381 static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params)
   382 {
   383 	char *str;
   384 	pContext->LocalToString(params[1], &str);
   385 
   386 	return g_PluginSys.LibraryExists(str) ? 1 : 0;
   387 }
   388 
   389 REGISTER_NATIVES(coreNatives)
   390 {
   391 	{"AutoExecConfig",			AutoExecConfig},
   392 	{"GetPluginFilename",		GetPluginFilename},
   393 	{"GetPluginInfo",			GetPluginInfo},
   394 	{"GetPluginIterator",		GetPluginIterator},
   395 	{"GetPluginStatus",			GetPluginStatus},
   396 	{"GetSysTickCount",			GetSysTickCount},
   397 	{"GetTime",					GetTime},
   398 	{"IsPluginDebugging",		IsPluginDebugging},
   399 	{"MorePlugins",				MorePlugins},
   400 	{"ReadPlugin",				ReadPlugin},
   401 	{"ThrowError",				ThrowError},
   402 	{"SetFailState",			SetFailState},
   403 	{"FormatTime",				FormatTime},
   404 	{"MarkNativeAsOptional",	MarkNativeAsOptional},
   405 	{"RegPluginLibrary",		RegPluginLibrary},
   406 	{"LibraryExists",			LibraryExists},
   407 	{NULL,						NULL},
   408 };