Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.
(This day shall henceforth be known as the Eighty Column Massacre of '07)
3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_globals.h"
33 #include "PluginSys.h"
34 #include "ForwardSys.h"
35 #include "HandleSys.h"
37 HandleType_t g_GlobalFwdType = 0;
38 HandleType_t g_PrivateFwdType = 0;
40 static bool s_CallStarted = false;
41 static ICallable *s_pCallable = NULL;
42 static IPluginFunction *s_pFunction = NULL;
43 static IForward *s_pForward = NULL;
45 class ForwardNativeHelpers :
47 public IHandleTypeDispatch
50 void OnSourceModAllInitialized()
54 /* Set GlobalFwd handle access security */
55 g_HandleSys.InitAccessDefaults(NULL, &sec);
56 sec.access[HandleAccess_Read] = 0;
57 sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
59 /* Create 'GlobalFwd' handle type */
60 g_GlobalFwdType = g_HandleSys.CreateType("GlobalFwd", this, 0, NULL, &sec, g_pCoreIdent, NULL);
62 /* Private forwards are cloneable */
63 sec.access[HandleAccess_Clone] = 0;
65 /* Create 'PrivateFwd' handle type */
66 g_PrivateFwdType = g_HandleSys.CreateType("PrivateFwd", this, g_GlobalFwdType, NULL, &sec, g_pCoreIdent, NULL);
69 void OnSourceModShutdown()
71 g_HandleSys.RemoveType(g_PrivateFwdType, g_pCoreIdent);
72 g_HandleSys.RemoveType(g_GlobalFwdType, g_pCoreIdent);
75 void OnHandleDestroy(HandleType_t type, void *object)
77 IForward *pForward = static_cast<IForward *>(object);
79 g_Forwards.ReleaseForward(pForward);
81 } g_ForwardNativeHelpers;
84 /* Turn a public index into a function ID */
85 inline funcid_t PublicIndexToFuncId(uint32_t idx)
87 return (idx << 1) | (1 << 0);
90 /* Reset global function/forward call variables */
91 inline void ResetCall()
93 s_CallStarted = false;
99 static cell_t sm_GetFunctionByName(IPluginContext *pContext, const cell_t *params)
101 Handle_t hndl = static_cast<Handle_t>(params[1]);
109 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
111 pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
115 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
119 pContext->LocalToString(params[2], &name);
121 /* Get public function index */
122 if (pPlugin->GetBaseContext()->FindPublicByName(name, &idx) == SP_ERROR_NOT_FOUND)
124 /* Return INVALID_FUNCTION if not found */
128 /* Return function ID */
129 return PublicIndexToFuncId(idx);
132 static cell_t sm_CreateGlobalForward(IPluginContext *pContext, const cell_t *params)
134 cell_t count = params[0];
136 ParamType forwardParams[SP_MAX_EXEC_PARAMS];
138 if (count - 2 > SP_MAX_EXEC_PARAMS)
140 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
143 pContext->LocalToString(params[1], &name);
146 for (int i = 3; i <= count; i++)
148 pContext->LocalToPhysAddr(params[i], &addr);
149 forwardParams[i - 3] = static_cast<ParamType>(*addr);
152 IForward *pForward = g_Forwards.CreateForward(name, static_cast<ExecType>(params[2]), count - 2, forwardParams);
154 return g_HandleSys.CreateHandle(g_GlobalFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
157 static cell_t sm_CreateForward(IPluginContext *pContext, const cell_t *params)
159 cell_t count = params[0];
160 ParamType forwardParams[SP_MAX_EXEC_PARAMS];
162 if (count - 1 > SP_MAX_EXEC_PARAMS)
164 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
168 for (int i = 2; i <= count; i++)
170 pContext->LocalToPhysAddr(params[i], &addr);
171 forwardParams[i - 2] = static_cast<ParamType>(*addr);
174 IChangeableForward *pForward = g_Forwards.CreateForwardEx(NULL, static_cast<ExecType>(params[1]), count - 1, forwardParams);
176 return g_HandleSys.CreateHandle(g_PrivateFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
179 static cell_t sm_GetForwardFunctionCount(IPluginContext *pContext, const cell_t *params)
181 Handle_t hndl = static_cast<Handle_t>(params[1]);
185 if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
188 return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
191 return pForward->GetFunctionCount();
194 static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params)
196 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
197 Handle_t plHandle = static_cast<Handle_t>(params[2]);
199 IChangeableForward *pForward;
202 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
205 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
210 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
212 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
216 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
220 IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
224 return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
227 return pForward->AddFunction(pFunction);
230 static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *params)
232 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
233 Handle_t plHandle = static_cast<Handle_t>(params[2]);
235 IChangeableForward *pForward;
238 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
241 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
246 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
248 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
252 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
256 IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
260 return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
263 return pForward->RemoveFunction(pFunction);
266 static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *params)
268 Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
269 Handle_t plHandle = static_cast<Handle_t>(params[2]);
271 IChangeableForward *pForward;
274 if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
277 return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
282 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
284 pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
288 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
292 return pForward->RemoveFunctionsOfPlugin(pPlugin);
295 static cell_t sm_CallStartFunction(IPluginContext *pContext, const cell_t *params)
303 return pContext->ThrowNativeError("Cannot start a call while one is already in progress");
306 hndl = static_cast<Handle_t>(params[1]);
310 pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
312 pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
316 return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
320 s_pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]);
324 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
327 s_pCallable = static_cast<ICallable *>(s_pFunction);
329 s_CallStarted = true;
334 static cell_t sm_CallStartForward(IPluginContext *pContext, const cell_t *params)
342 return pContext->ThrowNativeError("Cannot start a call while one is already in progress");
345 hndl = static_cast<Handle_t>(params[1]);
347 if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
350 return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
353 s_pForward = pForward;
355 s_pCallable = static_cast<ICallable *>(pForward);
357 s_CallStarted = true;
362 static cell_t sm_CallPushCell(IPluginContext *pContext, const cell_t *params)
368 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
371 err = s_pCallable->PushCell(params[1]);
375 s_pCallable->Cancel();
377 return pContext->ThrowNativeErrorEx(err, NULL);
383 static cell_t sm_CallPushCellRef(IPluginContext *pContext, const cell_t *params)
390 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
393 pContext->LocalToPhysAddr(params[1], &addr);
395 err = s_pCallable->PushCellByRef(addr);
399 s_pCallable->Cancel();
401 return pContext->ThrowNativeErrorEx(err, NULL);
407 static cell_t sm_CallPushFloat(IPluginContext *pContext, const cell_t *params)
413 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
416 err = s_pCallable->PushFloat(sp_ctof(params[1]));
420 s_pCallable->Cancel();
422 return pContext->ThrowNativeErrorEx(err, NULL);
428 static cell_t sm_CallPushFloatRef(IPluginContext *pContext, const cell_t *params)
435 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
438 pContext->LocalToPhysAddr(params[1], &addr);
440 err = s_pCallable->PushFloatByRef(reinterpret_cast<float *>(addr));
444 s_pCallable->Cancel();
446 return pContext->ThrowNativeErrorEx(err, NULL);
452 static cell_t sm_CallPushArray(IPluginContext *pContext, const cell_t *params)
459 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
462 pContext->LocalToPhysAddr(params[1], &addr);
464 err = s_pCallable->PushArray(addr, params[2]);
468 s_pCallable->Cancel();
470 return pContext->ThrowNativeErrorEx(err, NULL);
476 static cell_t sm_CallPushArrayEx(IPluginContext *pContext, const cell_t *params)
483 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
486 pContext->LocalToPhysAddr(params[1], &addr);
488 err = s_pCallable->PushArray(addr, params[2], params[3]);
492 s_pCallable->Cancel();
494 return pContext->ThrowNativeErrorEx(err, NULL);
500 static cell_t sm_CallPushString(IPluginContext *pContext, const cell_t *params)
507 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
510 pContext->LocalToString(params[1], &value);
512 err = s_pCallable->PushString(value);
516 s_pCallable->Cancel();
518 return pContext->ThrowNativeErrorEx(err, NULL);
524 static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params)
531 return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
534 pContext->LocalToString(params[1], &value);
536 err = s_pCallable->PushStringEx(value, params[2], params[3], params[4]);
540 s_pCallable->Cancel();
542 return pContext->ThrowNativeErrorEx(err, NULL);
548 static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
550 int err = SP_ERROR_NOT_RUNNABLE;
555 return pContext->ThrowNativeError("Cannot finish call when there is no call in progress");
558 pContext->LocalToPhysAddr(params[1], &result);
562 IPluginFunction *pFunction = s_pFunction;
564 err = pFunction->Execute(result);
565 } else if (s_pForward) {
566 IForward *pForward = s_pForward;
568 err = pForward->Execute(result, NULL);
574 static cell_t sm_CallCancel(IPluginContext *pContext, const cell_t *params)
578 return pContext->ThrowNativeError("Cannot cancel call when there is no call in progress");
581 s_pCallable->Cancel();
587 REGISTER_NATIVES(functionNatives)
589 {"GetFunctionByName", sm_GetFunctionByName},
590 {"CreateGlobalForward", sm_CreateGlobalForward},
591 {"CreateForward", sm_CreateForward},
592 {"GetForwardFunctionCount", sm_GetForwardFunctionCount},
593 {"AddToForward", sm_AddToForward},
594 {"RemoveFromForward", sm_RemoveFromForward},
595 {"RemoveAllFromForward", sm_RemoveAllFromForward},
596 {"Call_StartFunction", sm_CallStartFunction},
597 {"Call_StartForward", sm_CallStartForward},
598 {"Call_PushCell", sm_CallPushCell},
599 {"Call_PushCellRef", sm_CallPushCellRef},
600 {"Call_PushFloat", sm_CallPushFloat},
601 {"Call_PushFloatRef", sm_CallPushFloatRef},
602 {"Call_PushArray", sm_CallPushArray},
603 {"Call_PushArrayEx", sm_CallPushArrayEx},
604 {"Call_PushString", sm_CallPushString},
605 {"Call_PushStringEx", sm_CallPushStringEx},
606 {"Call_Finish", sm_CallFinish},
607 {"Call_Cancel", sm_CallCancel},