3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
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
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"
24 #if defined PLATFORM_WINDOWS
26 #elif defined PLATFORM_LINUX
29 #include <sys/times.h>
32 HandleType_t g_PlIter;
34 class CoreNativeHelpers :
36 public IHandleTypeDispatch
39 void OnSourceModAllInitialized()
42 g_HandleSys.InitAccessDefaults(NULL, &hacc);
43 hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
45 g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
47 void OnHandleDestroy(HandleType_t type, void *object)
49 IPluginIterator *iter = (IPluginIterator *)object;
52 void OnSourceModShutdown()
54 g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent);
56 } g_CoreNativeHelpers;
59 static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
63 g_SourceMod.SetGlobalTarget(LANG_SERVER);
65 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
67 if (pContext->GetContext()->n_err == SP_ERROR_NONE)
69 pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
75 static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
77 time_t t = time(NULL);
79 pContext->LocalToPhysAddr(params[1], &addr);
83 return static_cast<cell_t>(t);
86 static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
88 char *format, *buffer;
89 pContext->LocalToString(params[1], &buffer);
90 pContext->LocalToString(params[3], &format);
92 time_t t = (params[4] == -1) ? time(NULL) : (time_t)params[4];
93 strftime(buffer, params[2], format, localtime(&t));
98 static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
100 IPluginIterator *iter = g_PluginSys.GetPluginIterator();
102 Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
104 if (hndl == BAD_HANDLE)
112 static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
114 Handle_t hndl = (Handle_t)params[1];
116 IPluginIterator *pIter;
119 sec.pIdentity = g_pCoreIdent;
120 sec.pOwner = pContext->GetIdentity();
122 if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
124 return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
127 return pIter->MorePlugins() ? 1 : 0;
130 static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
132 Handle_t hndl = (Handle_t)params[1];
134 IPluginIterator *pIter;
137 sec.pIdentity = g_pCoreIdent;
138 sec.pOwner = pContext->GetIdentity();
140 if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
142 return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
145 CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin();
153 return pPlugin->GetMyHandle();
156 CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
158 if (hndl == BAD_HANDLE)
160 return g_PluginSys.GetPluginByCtx(pContext->GetContext());
163 CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err);
166 pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
172 static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
174 CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
180 return pPlugin->GetStatus();
183 static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
185 CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
191 pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
196 static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
198 CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
204 return pPlugin->IsDebugging() ? 1 : 0;
207 /* Local to plugins only */
210 PlInfo_Name, /**< Plugin name */
211 PlInfo_Author, /**< Plugin author */
212 PlInfo_Description, /**< Plugin description */
213 PlInfo_Version, /**< Plugin verison */
214 PlInfo_URL, /**< Plugin URL */
217 static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
219 CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
225 const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
232 const char *str = NULL;
234 switch ((PluginInfo)params[2])
246 case PlInfo_Description:
248 str = info->description;
263 if (!str || str[0] == '\0')
268 pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
273 static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
276 pContext->LocalToString(params[1], &str);
278 CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
279 pPlugin->SetErrorState(Plugin_Error, "%s", str);
281 return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
284 static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
286 #if defined PLATFORM_WINDOWS
287 return (cell_t)GetTickCount();
288 #elif defined PLATFORM_LINUX
290 clock_t ticks = times(&tm);
291 long ticks_per_sec = sysconf(_SC_CLK_TCK);
292 double fticks = (double)ticks / (double)ticks_per_sec;
294 if (fticks > INT_MAX)
296 double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
299 return (cell_t)fticks;
303 static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
305 CPlugin *plugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
308 pContext->LocalToString(params[2], &cfg);
309 pContext->LocalToString(params[3], &folder);
313 static char temp_str[255];
314 static char temp_file[PLATFORM_MAX_PATH];
317 g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
318 if ((ptr = strstr(temp_str, ".smx")) != NULL)
323 /* We have the raw filename! */
324 UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
328 plugin->AddConfig(params[1] ? true : false, cfg, folder);
333 static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *params)
337 sp_context_t *ctx = pContext->GetContext();
339 pContext->LocalToString(params[1], &name);
340 if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
342 return pContext->ThrowNativeError("Unable to find native \"%s\"", name);
345 ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL;
350 static cell_t RegPluginLibrary(IPluginContext *pContext, const cell_t *params)
353 CPlugin *pl = g_PluginSys.GetPluginByCtx(pContext->GetContext());
355 pContext->LocalToString(params[1], &name);
357 pl->AddLibrary(name);
362 REGISTER_NATIVES(coreNatives)
364 {"AutoExecConfig", AutoExecConfig},
365 {"GetPluginFilename", GetPluginFilename},
366 {"GetPluginInfo", GetPluginInfo},
367 {"GetPluginIterator", GetPluginIterator},
368 {"GetPluginStatus", GetPluginStatus},
369 {"GetSysTickCount", GetSysTickCount},
370 {"GetTime", GetTime},
371 {"IsPluginDebugging", IsPluginDebugging},
372 {"MorePlugins", MorePlugins},
373 {"ReadPlugin", ReadPlugin},
374 {"ThrowError", ThrowError},
375 {"SetFailState", SetFailState},
376 {"FormatTime", FormatTime},
377 {"MarkNativeAsOptional", MarkNativeAsOptional},
378 {"RegPluginLibrary", RegPluginLibrary},