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 "sourcemod.h"
34 #include "sourcemm_api.h"
35 #include "server_class.h"
36 #include "PlayerManager.h"
37 #include "HalfLife2.h"
38 #include "GameConfigs.h"
39 #include "sm_stringutil.h"
47 inline edict_t *GetEdict(cell_t num)
49 edict_t *pEdict = engine->PEntityOfEntIndex(num);
50 if (!pEdict || pEdict->IsFree())
54 if (num > 0 && num < g_Players.GetMaxClients())
56 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
57 if (!pPlayer || !pPlayer->IsConnected())
65 inline edict_t *GetEntity(cell_t num, CBaseEntity **pData)
67 edict_t *pEdict = engine->PEntityOfEntIndex(num);
68 if (!pEdict || pEdict->IsFree())
72 if (num > 0 && num < g_Players.GetMaxClients())
74 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
75 if (!pPlayer || !pPlayer->IsConnected())
81 if ((pUnk=pEdict->GetUnknown()) == NULL)
85 *pData = pUnk->GetBaseEntity();
90 datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
92 void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
93 void **vtable = *reinterpret_cast<void ***>(pThisPtr);
94 void *vfunc = vtable[offset];
98 datamap_t *(VEmptyClass::*mfpnew)();
99 #ifndef PLATFORM_POSIX
114 return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
117 inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
121 if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
126 return VGetDataDescMap(pEntity, offset);
129 /* :TODO: Move this! */
130 datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
132 return CBaseEntity_GetDataDescMap(pEntity);
135 static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
137 return gpGlobals->maxEntities;
140 static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
142 edict_t *pEdict = engine->CreateEdict();
149 return engine->IndexOfEdict(pEdict);
152 static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
154 edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
158 return pContext->ThrowNativeError("Edict %d is not a valid edict", params[1]);
161 engine->RemoveEdict(pEdict);
166 static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
168 edict_t *pEdict = GetEdict(params[1]);
175 /* Shouldn't be necessary... not sure though */
176 return pEdict->IsFree() ? 0 : 1;
179 static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
181 edict_t *pEdict = GetEdict(params[1]);
188 IServerUnknown *pUnknown = pEdict->GetUnknown();
194 CBaseEntity *pEntity = pUnknown->GetBaseEntity();
195 return (pEntity != NULL) ? 1 : 0;
198 static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
200 edict_t *pEdict = GetEdict(params[1]);
207 return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
210 static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
212 return engine->GetEntityCount();
215 static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
217 edict_t *pEdict = GetEdict(params[1]);
221 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
224 return pEdict->m_fStateFlags;
227 static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
229 edict_t *pEdict = GetEdict(params[1]);
233 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
236 pEdict->m_fStateFlags = params[2];
241 static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
243 edict_t *pEdict = GetEdict(params[1]);
247 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
250 const char *cls = pEdict->GetClassName();
252 if (!cls || cls[0] == '\0')
257 pContext->StringToLocal(params[2], params[3], cls);
262 static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
264 edict_t *pEdict = GetEdict(params[1]);
268 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
271 IServerNetworkable *pNet = pEdict->GetNetworkable();
277 ServerClass *pClass = pNet->GetServerClass();
279 pContext->StringToLocal(params[2], params[3], pClass->GetName());
284 static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
286 CBaseEntity *pEntity;
287 edict_t *pEdict = GetEntity(params[1], &pEntity);
289 if (!pEdict || !pEntity)
291 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
294 int offset = params[2];
295 if (offset < 0 || offset > 32768)
297 return pContext->ThrowNativeError("Offset %d is invalid", offset);
303 return *(int *)((uint8_t *)pEntity + offset);
305 return *(short *)((uint8_t *)pEntity + offset);
307 return *((uint8_t *)pEntity + offset);
309 return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
313 static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
315 CBaseEntity *pEntity;
316 edict_t *pEdict = GetEntity(params[1], &pEntity);
318 if (!pEdict || !pEntity)
320 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
323 int offset = params[2];
324 if (offset < 0 || offset > 32768)
326 return pContext->ThrowNativeError("Offset %d is invalid", offset);
331 g_HL2.SetEdictStateChanged(pEdict, offset);
338 *(int *)((uint8_t *)pEntity + offset) = params[3];
343 *(short *)((uint8_t *)pEntity + offset) = params[3];
348 *((uint8_t *)pEntity + offset) = params[3];
352 return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
358 static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
360 CBaseEntity *pEntity;
361 edict_t *pEdict = GetEntity(params[1], &pEntity);
363 if (!pEdict || !pEntity)
365 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
368 int offset = params[2];
369 if (offset < 0 || offset > 32768)
371 return pContext->ThrowNativeError("Offset %d is invalid", offset);
374 float f = *(float *)((uint8_t *)pEntity + offset);
379 static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
381 CBaseEntity *pEntity;
382 edict_t *pEdict = GetEntity(params[1], &pEntity);
384 if (!pEdict || !pEntity)
386 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
389 int offset = params[2];
390 if (offset < 0 || offset > 32768)
392 return pContext->ThrowNativeError("Offset %d is invalid", offset);
395 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
399 g_HL2.SetEdictStateChanged(pEdict, offset);
405 static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
407 CBaseEntity *pEntity;
408 edict_t *pEdict = GetEntity(params[1], &pEntity);
410 if (!pEdict || !pEntity)
412 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
415 int offset = params[2];
416 if (offset < 0 || offset > 32768)
418 return pContext->ThrowNativeError("Offset %d is invalid", offset);
421 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
424 pContext->LocalToPhysAddr(params[3], &vec);
426 vec[0] = sp_ftoc(v->x);
427 vec[1] = sp_ftoc(v->y);
428 vec[2] = sp_ftoc(v->z);
433 static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
435 CBaseEntity *pEntity;
436 edict_t *pEdict = GetEntity(params[1], &pEntity);
438 if (!pEdict || !pEntity)
440 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
443 int offset = params[2];
444 if (offset < 0 || offset > 32768)
446 return pContext->ThrowNativeError("Offset %d is invalid", offset);
449 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
452 pContext->LocalToPhysAddr(params[3], &vec);
454 v->x = sp_ctof(vec[0]);
455 v->y = sp_ctof(vec[1]);
456 v->z = sp_ctof(vec[2]);
460 g_HL2.SetEdictStateChanged(pEdict, offset);
466 static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
468 CBaseEntity *pEntity;
469 edict_t *pEdict = GetEntity(params[1], &pEntity);
471 if (!pEdict || !pEntity)
473 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
476 int offset = params[2];
477 if (offset < 0 || offset > 32768)
479 return pContext->ThrowNativeError("Offset %d is invalid", offset);
482 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
489 /* :TODO: check serial no.? */
491 return hndl.GetEntryIndex();
494 static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
496 CBaseEntity *pEntity;
497 edict_t *pEdict = GetEntity(params[1], &pEntity);
499 if (!pEdict || !pEntity)
501 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
504 int offset = params[2];
505 if (offset < 0 || offset > 32768)
507 return pContext->ThrowNativeError("Offset %d is invalid", offset);
510 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
516 edict_t *pEdict = GetEdict(params[3]);
519 return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
521 IServerEntity *pEntOther = pEdict->GetIServerEntity();
527 g_HL2.SetEdictStateChanged(pEdict, offset);
533 static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
535 edict_t *pEdict = GetEdict(params[1]);
539 return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
542 g_HL2.SetEdictStateChanged(pEdict, params[2]);
547 static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
550 pContext->LocalToString(params[1], &cls);
551 pContext->LocalToString(params[2], &prop);
553 SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
560 return pSend->GetOffset();
563 static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
565 CBaseEntity *pEntity;
567 typedescription_t *td;
569 edict_t *pEdict = GetEntity(params[1], &pEntity);
571 if (!pEdict || !pEntity)
573 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
576 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
578 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
581 pContext->LocalToString(params[2], &offset);
582 if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
587 return td->fieldOffset[TD_OFFSET_NORMAL];
590 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
592 CBaseEntity *pEntity;
593 edict_t *pEdict = GetEntity(params[1], &pEntity);
595 if (!pEdict || !pEntity)
597 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
600 int offset = params[2];
601 if (offset < 0 || offset > 32768)
603 return pContext->ThrowNativeError("Offset %d is invalid", offset);
607 char *src = (char *)((uint8_t *)pEntity + offset);
608 pContext->StringToLocalUTF8(params[3], params[4], src, &len);
613 static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
615 CBaseEntity *pEntity;
616 edict_t *pEdict = GetEntity(params[1], &pEntity);
618 if (!pEdict || !pEntity)
620 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
623 int offset = params[2];
624 if (offset < 0 || offset > 32768)
626 return pContext->ThrowNativeError("Offset %d is invalid", offset);
630 char *dest = (char *)((uint8_t *)pEntity + offset);
632 pContext->LocalToString(params[3], &src);
633 size_t len = strncopy(dest, src, params[4]);
637 g_HL2.SetEdictStateChanged(pEdict, offset);
643 static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
645 CBaseEntity *pEntity;
648 edict_t *pEdict = GetEntity(params[1], &pEntity);
650 if (!pEdict || !pEntity)
652 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
660 typedescription_t *td;
661 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
663 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
665 pContext->LocalToString(params[3], &prop);
666 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
668 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
670 if (td->fieldType != FIELD_CHARACTER)
672 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
674 offset = td->fieldOffset[TD_OFFSET_NORMAL];
680 IServerNetworkable *pNet = pEdict->GetNetworkable();
683 return pContext->ThrowNativeError("The edict is not networkable");
685 pContext->LocalToString(params[3], &prop);
686 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
689 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
691 if (pSend->GetType() != DPT_String)
693 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
695 offset = pSend->GetOffset();
700 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
705 char *src = (char *)((uint8_t *)pEntity + offset);
706 pContext->StringToLocalUTF8(params[4], params[5], src, &len);
711 static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
713 CBaseEntity *pEntity;
717 bool is_sendprop = false;
718 edict_t *pEdict = GetEntity(params[1], &pEntity);
720 if (!pEdict || !pEntity)
722 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
730 typedescription_t *td;
731 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
733 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
735 pContext->LocalToString(params[3], &prop);
736 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
738 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
740 if (td->fieldType != FIELD_CHARACTER)
742 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
744 offset = td->fieldOffset[TD_OFFSET_NORMAL];
745 maxlen = td->fieldSize;
751 IServerNetworkable *pNet = pEdict->GetNetworkable();
754 return pContext->ThrowNativeError("The edict is not networkable");
756 pContext->LocalToString(params[3], &prop);
757 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
760 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
762 if (pSend->GetType() != DPT_String)
764 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
766 offset = pSend->GetOffset();
767 maxlen = DT_MAX_STRING_BUFFERSIZE;
773 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
778 char *dest = (char *)((uint8_t *)pEntity + offset);
780 pContext->LocalToString(params[4], &src);
781 size_t len = strncopy(dest, src, maxlen);
785 g_HL2.SetEdictStateChanged(pEdict, offset);
791 REGISTER_NATIVES(entityNatives)
793 {"ChangeEdictState", ChangeEdictState},
794 {"CreateEdict", CreateEdict},
795 {"FindSendPropOffs", FindSendPropOffs},
796 {"GetEdictClassname", GetEdictClassname},
797 {"GetEdictFlags", GetEdictFlags},
798 {"GetEntData", GetEntData},
799 {"GetEntDataEnt", GetEntDataEnt},
800 {"GetEntDataFloat", GetEntDataFloat},
801 {"GetEntDataVector", GetEntDataVector},
802 {"GetEntityCount", GetEntityCount},
803 {"GetEntityNetClass", GetEntityNetClass},
804 {"GetMaxEntities", GetMaxEntities},
805 {"IsEntNetworkable", IsEntNetworkable},
806 {"IsValidEdict", IsValidEdict},
807 {"IsValidEntity", IsValidEntity},
808 {"RemoveEdict", RemoveEdict},
809 {"SetEdictFlags", SetEdictFlags},
810 {"SetEntData", SetEntData},
811 {"SetEntDataEnt", SetEntDataEnt},
812 {"SetEntDataFloat", SetEntDataFloat},
813 {"SetEntDataVector", SetEntDataVector},
814 {"FindDataMapOffs", FindDataMapOffs},
815 {"GetEntDataString", GetEntDataString},
816 {"SetEntDataString", SetEntDataString},
817 {"GetEntPropString", GetEntPropString},
818 {"SetEntPropString", SetEntPropString},