Added VOICE_TEAM and VOICE_LISTENTEAM flags to the SDKTools voice functionality.
3 * =============================================================================
4 * SourceMod SDKTools Extension
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 "extension.h"
33 #include "vcallbuilder.h"
38 SDKLibrary_Server, /**< server.dll/server_i486.so */
39 SDKLibrary_Engine, /**< engine.dll/engine_*.so */
44 SDKPass_Pointer, /**< Pass as a pointer */
45 SDKPass_Plain, /**< Pass as plain data */
46 SDKPass_ByValue, /**< Pass an object by value */
47 SDKPass_ByRef, /**< Pass an object by reference */
50 int s_vtbl_index = -1;
51 void *s_call_addr = NULL;
52 ValveCallType s_vcalltype = ValveCall_Static;
53 bool s_has_return = false;
54 ValvePassInfo s_return;
55 unsigned int s_numparams = 0;
56 ValvePassInfo s_params[SP_MAX_EXEC_PARAMS];
58 inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &type, unsigned int &flags)
60 if (method == SDKPass_Pointer || method == SDKPass_ByRef)
62 type = PassType_Basic;
63 if (vtype == Valve_POD
64 || vtype == Valve_Float
65 || vtype == Valve_Bool)
67 flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
69 flags = PASSFLAG_BYVAL;
71 } else if (method == SDKPass_Plain) {
72 type = PassType_Basic;
73 flags = PASSFLAG_BYVAL;
74 } else if (method == SDKPass_ByValue) {
75 if (vtype == Valve_Vector
76 || vtype == Valve_QAngle)
78 type = PassType_Object;
80 type = PassType_Basic;
82 flags = PASSFLAG_BYVAL;
86 static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
92 s_vcalltype = (ValveCallType)params[1];
97 static cell_t PrepSDKCall_SetVirtual(IPluginContext *pContext, const cell_t *params)
99 s_vtbl_index = params[1];
104 static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *params)
106 void *addrInBase = NULL;
107 if (params[1] == SDKLibrary_Server)
109 addrInBase = (void *)g_SMAPI->serverFactory(false);
110 } else if (params[1] == SDKLibrary_Engine) {
111 addrInBase = (void *)g_SMAPI->engineFactory(false);
113 if (addrInBase == NULL)
119 pContext->LocalToString(params[2], &sig);
121 #if defined PLATFORM_LINUX
125 if (dladdr(addrInBase, &info) == 0)
129 void *handle = dlopen(info.dli_fname, RTLD_NOW);
134 s_call_addr = dlsym(handle, &sig[1]);
137 return (s_call_addr != NULL) ? 1 : 0;
141 s_call_addr = memutils->FindPattern(addrInBase, sig, params[3]);
143 return (s_call_addr != NULL) ? 1 : 0;
146 static cell_t PrepSDKCall_SetFromConf(IPluginContext *pContext, const cell_t *params)
150 if (params[1] == BAD_HANDLE)
155 if ((conf = gameconfs->ReadHandle(params[1], pContext->GetIdentity(), &err)) == NULL)
157 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
162 pContext->LocalToString(params[3], &key);
166 return conf->GetOffset(key, &s_vtbl_index) ? 1 : 0;
167 } else if (params[2] == 1) {
168 bool result = conf->GetMemSig(key, &s_call_addr) ? 1 : 0;
169 return (result && s_call_addr != NULL) ? 1 : 0;
175 static cell_t PrepSDKCall_SetReturnInfo(IPluginContext *pContext, const cell_t *params)
178 s_return.vtype = (ValveType)params[1];
179 DecodePassMethod(s_return.vtype, (SDKPassMethod)params[2], s_return.type, s_return.flags);
180 s_return.decflags = params[3];
181 s_return.encflags = params[4];
186 static cell_t PrepSDKCall_AddParameter(IPluginContext *pContext, const cell_t *params)
188 if (s_numparams >= SP_MAX_EXEC_PARAMS)
190 return pContext->ThrowNativeError("Parameter limit for SDK calls reached");
193 ValvePassInfo *info = &s_params[s_numparams++];
194 info->vtype = (ValveType)params[1];
195 SDKPassMethod method = (SDKPassMethod)params[2];
196 DecodePassMethod(info->vtype, method, info->type, info->flags);
197 info->decflags = params[3] | VDECODE_FLAG_BYREF;
198 info->encflags = params[4];
200 /* Since SDKPass_ByRef acts like SDKPass_Pointer we can't allow NULL, just in case */
201 if (method == SDKPass_ByRef)
203 info->decflags &= ~VDECODE_FLAG_ALLOWNULL;
209 static cell_t EndPrepSDKCall(IPluginContext *pContext, const cell_t *params)
211 ValveCall *vc = NULL;
212 if (s_vtbl_index > -1)
214 vc = CreateValveVCall(s_vtbl_index, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
215 } else if (s_call_addr) {
216 vc = CreateValveCall(s_call_addr, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
226 vc->thisinfo->decflags |= VDECODE_FLAG_BYREF;
229 Handle_t hndl = handlesys->CreateHandle(g_CallHandle, vc, pContext->GetIdentity(), myself->GetIdentity(), NULL);
238 static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
242 HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
244 if ((err = handlesys->ReadHandle(params[1], g_CallHandle, &sec, (void **)&vc)) != HandleError_None)
246 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
249 unsigned char *ptr = vc->stk_get();
251 unsigned int numparams = (unsigned)params[0];
252 unsigned int startparam = 2;
253 /* Do we need to write a thispointer? */
259 case ValveCall_Entity:
260 case ValveCall_Player:
262 if (startparam > numparams)
265 return pContext->ThrowNativeError("Expected 1 parameter for entity pointer; found none");
268 if (DecodeValveParam(pContext,
280 case ValveCall_GameRules:
282 if (g_pGameRules == NULL)
285 return pContext->ThrowNativeError("GameRules unsupported or not available; file a bug report");
288 void *gamerules = *g_pGameRules;
290 if (gamerules == NULL)
293 return pContext->ThrowNativeError("GameRules not available before map is loaded");
295 *(void **)ptr = gamerules;
298 case ValveCall_EntityList:
300 if (g_EntList == NULL)
303 return pContext->ThrowNativeError("EntityList unsupported or not available; file a bug report");
306 *(void **)ptr = g_EntList;
312 /* See if we need to skip any more parameters */
313 unsigned int retparam = startparam;
316 if (vc->retinfo->vtype == Valve_String)
319 } else if (vc->retinfo->vtype == Valve_Vector
320 || vc->retinfo->vtype == Valve_QAngle)
326 unsigned int callparams = vc->call->GetParamCount();
327 bool will_copyback = false;
328 for (unsigned int i=0; i<callparams; i++)
330 unsigned int p = startparam + i;
334 return pContext->ThrowNativeError("Expected %dth parameter, found none", p);
336 if (DecodeValveParam(pContext,
345 if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
347 will_copyback = true;
351 /* Make the actual call */
352 vc->call->Execute(ptr, vc->retbuf);
354 /* Do we need to copy anything back? */
357 for (unsigned int i=0; i<callparams; i++)
359 if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
361 if (EncodeValveParam(pContext,
362 params[startparam + i],
374 /* Save stack once and for all */
377 /* Figure out how to decode the return information */
380 if (vc->retinfo->vtype == Valve_String)
384 return pContext->ThrowNativeError("Expected arguments (2,3) for string storage");
388 pContext->LocalToPhysAddr(params[retparam+1], &addr);
389 pContext->StringToLocalUTF8(params[retparam], *addr, *(char **)vc->retbuf, &written);
390 return (cell_t)written;
391 } else if (vc->retinfo->vtype == Valve_Vector
392 || vc->retinfo->vtype == Valve_QAngle)
396 return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
398 if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
403 } else if (vc->retinfo->vtype == Valve_CBaseEntity
404 || vc->retinfo->vtype == Valve_CBasePlayer)
406 CBaseEntity *pEntity = *(CBaseEntity **)(vc->retbuf);
411 edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
412 if (!pEdict || pEdict->IsFree())
416 return engine->IndexOfEdict(pEdict);
417 } else if (vc->retinfo->vtype == Valve_Edict) {
418 edict_t *pEdict = *(edict_t **)(vc->retbuf);
419 if (!pEdict || pEdict->IsFree())
423 return engine->IndexOfEdict(pEdict);
424 } else if (vc->retinfo->vtype == Valve_Bool) {
425 bool *addr = (bool *)vc->retbuf;
426 if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
428 addr = *(bool **)addr;
430 return *addr ? 1 : 0;
432 cell_t *addr = (cell_t *)vc->retbuf;
433 if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
435 addr = *(cell_t **)addr;
444 sp_nativeinfo_t g_CallNatives[] =
446 {"StartPrepSDKCall", StartPrepSDKCall},
447 {"PrepSDKCall_SetVirtual", PrepSDKCall_SetVirtual},
448 {"PrepSDKCall_SetSignature", PrepSDKCall_SetSignature},
449 {"PrepSDKCall_SetFromConf", PrepSDKCall_SetFromConf},
450 {"PrepSDKCall_SetReturnInfo", PrepSDKCall_SetReturnInfo},
451 {"PrepSDKCall_AddParameter", PrepSDKCall_AddParameter},
452 {"EndPrepSDKCall", EndPrepSDKCall},
453 {"SDKCall", SDKCall},