core/smn_core.cpp
author Scott Ehlert <ds@alliedmods.net>
Fri Jun 22 15:37:12 2007 +0000 (2007-06-22)
changeset 1001 8de56a71f200
parent 978 54782a83a1ef
child 1011 b413072540fd
permissions -rw-r--r--
Implemented amb423 - Added IsClientObserver() native
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include <time.h>
    16 #include <string.h>
    17 #include "sm_stringutil.h"
    18 #include "sm_globals.h"
    19 #include "sourcemod.h"
    20 #include "PluginSys.h"
    21 #include "HandleSys.h"
    22 #include "LibrarySys.h"
    23 
    24 #if defined PLATFORM_WINDOWS
    25 #include <windows.h>
    26 #elif defined PLATFORM_LINUX
    27 #include <limits.h>
    28 #include <unistd.h>
    29 #include <sys/times.h>
    30 #endif
    31 
    32 HandleType_t g_PlIter;
    33 
    34 class CoreNativeHelpers : 
    35 	public SMGlobalClass,
    36 	public IHandleTypeDispatch
    37 {
    38 public:
    39 	void OnSourceModAllInitialized()
    40 	{
    41 		HandleAccess hacc;
    42 		g_HandleSys.InitAccessDefaults(NULL,  &hacc);
    43 		hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
    44 
    45 		g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    46 	}
    47 	void OnHandleDestroy(HandleType_t type, void *object)
    48 	{
    49 		IPluginIterator *iter = (IPluginIterator *)object;
    50 		iter->Release();
    51 	}
    52 	void OnSourceModShutdown()
    53 	{
    54 		g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent);
    55 	}
    56 } g_CoreNativeHelpers;
    57 
    58 
    59 static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
    60 {
    61 	char buffer[512];
    62 
    63 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
    64 
    65 	if (pContext->GetContext()->n_err == SP_ERROR_NONE)
    66 	{
    67 		pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
    68 	}
    69 
    70 	return 0;
    71 }
    72 
    73 static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
    74 {
    75 	time_t t = time(NULL);
    76 	cell_t *addr;
    77 	pContext->LocalToPhysAddr(params[1], &addr);
    78 
    79 	*(time_t *)addr = t;
    80 
    81 	return static_cast<cell_t>(t);
    82 }
    83 
    84 static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
    85 {
    86 	IPluginIterator *iter = g_PluginSys.GetPluginIterator();
    87 
    88 	Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
    89 
    90 	if (hndl == BAD_HANDLE)
    91 	{
    92 		iter->Release();
    93 	}
    94 
    95 	return hndl;
    96 }
    97 
    98 static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
    99 {
   100 	Handle_t hndl = (Handle_t)params[1];
   101 	HandleError err;
   102 	IPluginIterator *pIter;
   103 
   104 	HandleSecurity sec;
   105 	sec.pIdentity = g_pCoreIdent;
   106 	sec.pOwner = pContext->GetIdentity();
   107 
   108 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   109 	{
   110 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   111 	}
   112 
   113 	return pIter->MorePlugins() ? 1 : 0;
   114 }
   115 
   116 static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
   117 {
   118 	Handle_t hndl = (Handle_t)params[1];
   119 	HandleError err;
   120 	IPluginIterator *pIter;
   121 
   122 	HandleSecurity sec;
   123 	sec.pIdentity = g_pCoreIdent;
   124 	sec.pOwner = pContext->GetIdentity();
   125 
   126 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   127 	{
   128 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   129 	}
   130 
   131 	CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin();
   132 	if (!pPlugin)
   133 	{
   134 		return BAD_HANDLE;
   135 	}
   136 
   137 	pIter->NextPlugin();
   138 
   139 	return pPlugin->GetMyHandle();
   140 }
   141 
   142 CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
   143 {
   144 	if (hndl == BAD_HANDLE)
   145 	{
   146 		return g_PluginSys.GetPluginByCtx(pContext->GetContext());
   147 	} else {
   148 		HandleError err;
   149 		CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err);
   150 		if (!pPlugin)
   151 		{
   152 			pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   153 		}
   154 		return pPlugin;
   155 	}
   156 }
   157 
   158 static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
   159 {
   160 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   161 	if (!pPlugin)
   162 	{
   163 		return 0;
   164 	}
   165 
   166 	return pPlugin->GetStatus();
   167 }
   168 
   169 static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
   170 {
   171 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   172 	if (!pPlugin)
   173 	{
   174 		return 0;
   175 	}
   176 
   177 	pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
   178 
   179 	return 1;
   180 }
   181 
   182 static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
   183 {
   184 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   185 	if (!pPlugin)
   186 	{
   187 		return 0;
   188 	}
   189 
   190 	return pPlugin->IsDebugging() ? 1 : 0;
   191 }
   192 
   193 /* Local to plugins only */
   194 enum PluginInfo
   195 {
   196 	PlInfo_Name,			/**< Plugin name */
   197 	PlInfo_Author,			/**< Plugin author */
   198 	PlInfo_Description,		/**< Plugin description */
   199 	PlInfo_Version,			/**< Plugin verison */
   200 	PlInfo_URL,				/**< Plugin URL */
   201 };
   202 
   203 static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
   204 {
   205 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   206 	if (!pPlugin)
   207 	{
   208 		return 0;
   209 	}
   210 
   211 	const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
   212 
   213 	if (!info)
   214 	{
   215 		return 0;
   216 	}
   217 
   218 	const char *str = NULL;
   219 
   220 	switch ((PluginInfo)params[2])
   221 	{
   222 	case PlInfo_Name:
   223 		{
   224 			str = info->name;
   225 			break;
   226 		}
   227 	case PlInfo_Author:
   228 		{
   229 			str = info->author;
   230 			break;
   231 		}
   232 	case PlInfo_Description:
   233 		{
   234 			str = info->description;
   235 			break;
   236 		}
   237 	case PlInfo_Version:
   238 		{
   239 			str = info->version;
   240 			break;
   241 		}
   242 	case PlInfo_URL:
   243 		{
   244 			str = info->url;
   245 			break;
   246 		}
   247 	}
   248 
   249 	if (!str || str[0] == '\0')
   250 	{
   251 		return 0;
   252 	}
   253 
   254 	pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
   255 
   256 	return 1;
   257 }
   258 
   259 static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
   260 {
   261 	char *str;
   262 	pContext->LocalToString(params[1], &str);
   263 
   264 	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   265 	pPlugin->SetErrorState(Plugin_Error, "%s", str);
   266 
   267 	return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
   268 }
   269 
   270 static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
   271 {
   272 #if defined PLATFORM_WINDOWS
   273 	return (cell_t)GetTickCount();
   274 #elif defined PLATFORM_LINUX
   275 	tms tm;
   276 	clock_t ticks = times(&tm);
   277 	long ticks_per_sec = sysconf(_SC_CLK_TCK);
   278 	double fticks = (double)ticks / (double)ticks_per_sec;
   279 	fticks *= 1000.0f;
   280 	if (fticks > INT_MAX)
   281 	{
   282 		double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
   283 		fticks -= r;
   284 	}
   285 	return (cell_t)fticks;
   286 #endif
   287 }
   288 
   289 static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
   290 {
   291 	CPlugin *plugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   292 
   293 	char *cfg, *folder;
   294 	pContext->LocalToString(params[2], &cfg);
   295 	pContext->LocalToString(params[3], &folder);
   296 
   297 	if (cfg[0] == '\0')
   298 	{
   299 		static char temp_str[255];
   300 		static char temp_file[PLATFORM_MAX_PATH];
   301 		char *ptr;
   302 
   303 		g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
   304 		if ((ptr = strstr(temp_str, ".smx")) != NULL)
   305 		{
   306 			*ptr = '\0';
   307 		}
   308 
   309 		/* We have the raw filename! */
   310 		UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
   311 		cfg = temp_file;
   312 	}
   313 
   314 	plugin->AddConfig(params[1] ? true : false, cfg, folder);
   315 
   316 	return 1;
   317 }
   318 
   319 REGISTER_NATIVES(coreNatives)
   320 {
   321 	{"AutoExecConfig",		AutoExecConfig},
   322 	{"GetPluginFilename",	GetPluginFilename},
   323 	{"GetPluginInfo",		GetPluginInfo},
   324 	{"GetPluginIterator",	GetPluginIterator},
   325 	{"GetPluginStatus",		GetPluginStatus},
   326 	{"GetSysTickCount",		GetSysTickCount},
   327 	{"GetTime",				GetTime},
   328 	{"IsPluginDebugging",	IsPluginDebugging},
   329 	{"MorePlugins",			MorePlugins},
   330 	{"ReadPlugin",			ReadPlugin},
   331 	{"ThrowError",			ThrowError},
   332 	{"SetFailState",		SetFailState},
   333 	{NULL,					NULL},
   334 };