fixed a state bug in the gameconf parser that would break parsing after a signature section was done
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
15 #include "sm_globals.h"
16 #include "sourcemod.h"
17 #include "sourcemm_api.h"
18 #include "server_class.h"
19 #include "PlayerManager.h"
20 #include "HalfLife2.h"
21 #include "GameConfigs.h"
22 #include "sm_stringutil.h"
30 inline edict_t *GetEdict(cell_t num)
32 edict_t *pEdict = engine->PEntityOfEntIndex(num);
33 if (!pEdict || pEdict->IsFree())
37 if (num > 0 && num < g_Players.GetMaxClients())
39 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
40 if (!pPlayer || !pPlayer->IsConnected())
48 inline edict_t *GetEntity(cell_t num, CBaseEntity **pData)
50 edict_t *pEdict = engine->PEntityOfEntIndex(num);
51 if (!pEdict || pEdict->IsFree())
55 if (num > 0 && num < g_Players.GetMaxClients())
57 CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
58 if (!pPlayer || !pPlayer->IsConnected())
64 if ((pUnk=pEdict->GetUnknown()) == NULL)
68 *pData = pUnk->GetBaseEntity();
73 datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
75 void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
76 void **vtable = *reinterpret_cast<void ***>(pThisPtr);
77 void *vfunc = vtable[offset];
81 datamap_t *(VEmptyClass::*mfpnew)();
82 #ifndef PLATFORM_POSIX
97 return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
100 inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
104 if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
109 return VGetDataDescMap(pEntity, offset);
112 /* :TODO: Move this! */
113 datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
115 return CBaseEntity_GetDataDescMap(pEntity);
118 static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
120 return gpGlobals->maxEntities;
123 static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
125 edict_t *pEdict = engine->CreateEdict();
132 return engine->IndexOfEdict(pEdict);
135 static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
137 edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
141 return pContext->ThrowNativeError("Edict %d is not a valid edict", params[1]);
144 engine->RemoveEdict(pEdict);
149 static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
151 edict_t *pEdict = GetEdict(params[1]);
158 /* Shouldn't be necessary... not sure though */
159 return pEdict->IsFree() ? 0 : 1;
162 static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
164 edict_t *pEdict = GetEdict(params[1]);
171 IServerUnknown *pUnknown = pEdict->GetUnknown();
177 CBaseEntity *pEntity = pUnknown->GetBaseEntity();
178 return (pEntity != NULL) ? 1 : 0;
181 static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
183 edict_t *pEdict = GetEdict(params[1]);
190 return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
193 static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
195 return engine->GetEntityCount();
198 static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
200 edict_t *pEdict = GetEdict(params[1]);
204 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
207 return pEdict->m_fStateFlags;
210 static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
212 edict_t *pEdict = GetEdict(params[1]);
216 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
219 pEdict->m_fStateFlags = params[2];
224 static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
226 edict_t *pEdict = GetEdict(params[1]);
230 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
233 const char *cls = pEdict->GetClassName();
235 if (!cls || cls[0] == '\0')
240 pContext->StringToLocal(params[2], params[3], cls);
245 static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
247 edict_t *pEdict = GetEdict(params[1]);
251 return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
254 IServerNetworkable *pNet = pEdict->GetNetworkable();
260 ServerClass *pClass = pNet->GetServerClass();
262 pContext->StringToLocal(params[2], params[3], pClass->GetName());
267 static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
269 CBaseEntity *pEntity;
270 edict_t *pEdict = GetEntity(params[1], &pEntity);
272 if (!pEdict || !pEntity)
274 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
277 int offset = params[2];
278 if (offset < 0 || offset > 32768)
280 return pContext->ThrowNativeError("Offset %d is invalid", offset);
286 return *(int *)((uint8_t *)pEntity + offset);
288 return *(short *)((uint8_t *)pEntity + offset);
290 return *((uint8_t *)pEntity + offset);
292 return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
296 static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
298 CBaseEntity *pEntity;
299 edict_t *pEdict = GetEntity(params[1], &pEntity);
301 if (!pEdict || !pEntity)
303 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
306 int offset = params[2];
307 if (offset < 0 || offset > 32768)
309 return pContext->ThrowNativeError("Offset %d is invalid", offset);
314 g_HL2.SetEdictStateChanged(pEdict, offset);
321 *(int *)((uint8_t *)pEntity + offset) = params[3];
326 *(short *)((uint8_t *)pEntity + offset) = params[3];
331 *((uint8_t *)pEntity + offset) = params[3];
335 return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
341 static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
343 CBaseEntity *pEntity;
344 edict_t *pEdict = GetEntity(params[1], &pEntity);
346 if (!pEdict || !pEntity)
348 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
351 int offset = params[2];
352 if (offset < 0 || offset > 32768)
354 return pContext->ThrowNativeError("Offset %d is invalid", offset);
357 float f = *(float *)((uint8_t *)pEntity + offset);
362 static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
364 CBaseEntity *pEntity;
365 edict_t *pEdict = GetEntity(params[1], &pEntity);
367 if (!pEdict || !pEntity)
369 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
372 int offset = params[2];
373 if (offset < 0 || offset > 32768)
375 return pContext->ThrowNativeError("Offset %d is invalid", offset);
378 *(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
382 g_HL2.SetEdictStateChanged(pEdict, offset);
388 static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
390 CBaseEntity *pEntity;
391 edict_t *pEdict = GetEntity(params[1], &pEntity);
393 if (!pEdict || !pEntity)
395 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
398 int offset = params[2];
399 if (offset < 0 || offset > 32768)
401 return pContext->ThrowNativeError("Offset %d is invalid", offset);
404 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
407 pContext->LocalToPhysAddr(params[3], &vec);
409 vec[0] = sp_ftoc(v->x);
410 vec[1] = sp_ftoc(v->y);
411 vec[2] = sp_ftoc(v->z);
416 static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
418 CBaseEntity *pEntity;
419 edict_t *pEdict = GetEntity(params[1], &pEntity);
421 if (!pEdict || !pEntity)
423 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
426 int offset = params[2];
427 if (offset < 0 || offset > 32768)
429 return pContext->ThrowNativeError("Offset %d is invalid", offset);
432 Vector *v = (Vector *)((uint8_t *)pEntity + offset);
435 pContext->LocalToPhysAddr(params[3], &vec);
437 v->x = sp_ctof(vec[0]);
438 v->y = sp_ctof(vec[1]);
439 v->z = sp_ctof(vec[2]);
443 g_HL2.SetEdictStateChanged(pEdict, offset);
449 static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
451 CBaseEntity *pEntity;
452 edict_t *pEdict = GetEntity(params[1], &pEntity);
454 if (!pEdict || !pEntity)
456 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
459 int offset = params[2];
460 if (offset < 0 || offset > 32768)
462 return pContext->ThrowNativeError("Offset %d is invalid", offset);
465 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
472 /* :TODO: check serial no.? */
474 return hndl.GetEntryIndex();
477 static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
479 CBaseEntity *pEntity;
480 edict_t *pEdict = GetEntity(params[1], &pEntity);
482 if (!pEdict || !pEntity)
484 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
487 int offset = params[2];
488 if (offset < 0 || offset > 32768)
490 return pContext->ThrowNativeError("Offset %d is invalid", offset);
493 CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
499 edict_t *pEdict = GetEdict(params[3]);
502 return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
504 IServerEntity *pEntOther = pEdict->GetIServerEntity();
510 g_HL2.SetEdictStateChanged(pEdict, offset);
516 static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
518 edict_t *pEdict = GetEdict(params[1]);
522 return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
525 g_HL2.SetEdictStateChanged(pEdict, params[2]);
530 static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
533 pContext->LocalToString(params[1], &cls);
534 pContext->LocalToString(params[2], &prop);
536 SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
543 return pSend->GetOffset();
546 static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
548 CBaseEntity *pEntity;
550 typedescription_t *td;
552 edict_t *pEdict = GetEntity(params[1], &pEntity);
554 if (!pEdict || !pEntity)
556 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
559 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
561 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
564 pContext->LocalToString(params[2], &offset);
565 if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
570 return td->fieldOffset[TD_OFFSET_NORMAL];
573 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
575 CBaseEntity *pEntity;
576 edict_t *pEdict = GetEntity(params[1], &pEntity);
578 if (!pEdict || !pEntity)
580 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
583 int offset = params[2];
584 if (offset < 0 || offset > 32768)
586 return pContext->ThrowNativeError("Offset %d is invalid", offset);
590 char *src = (char *)((uint8_t *)pEntity + offset);
591 pContext->StringToLocalUTF8(params[3], params[4], src, &len);
596 static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
598 CBaseEntity *pEntity;
599 edict_t *pEdict = GetEntity(params[1], &pEntity);
601 if (!pEdict || !pEntity)
603 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
606 int offset = params[2];
607 if (offset < 0 || offset > 32768)
609 return pContext->ThrowNativeError("Offset %d is invalid", offset);
613 char *dest = (char *)((uint8_t *)pEntity + offset);
615 pContext->LocalToString(params[3], &src);
616 size_t len = strncopy(dest, src, params[4]);
620 g_HL2.SetEdictStateChanged(pEdict, offset);
626 static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
628 CBaseEntity *pEntity;
631 edict_t *pEdict = GetEntity(params[1], &pEntity);
633 if (!pEdict || !pEntity)
635 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
643 typedescription_t *td;
644 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
646 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
648 pContext->LocalToString(params[3], &prop);
649 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
651 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
653 if (td->fieldType != FIELD_CHARACTER)
655 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
657 offset = td->fieldOffset[TD_OFFSET_NORMAL];
663 IServerNetworkable *pNet = pEdict->GetNetworkable();
666 return pContext->ThrowNativeError("The edict is not networkable");
668 pContext->LocalToString(params[3], &prop);
669 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
672 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
674 if (pSend->GetType() != DPT_String)
676 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
678 offset = pSend->GetOffset();
683 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
688 char *src = (char *)((uint8_t *)pEntity + offset);
689 pContext->StringToLocalUTF8(params[4], params[5], src, &len);
694 static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
696 CBaseEntity *pEntity;
700 bool is_sendprop = false;
701 edict_t *pEdict = GetEntity(params[1], &pEntity);
703 if (!pEdict || !pEntity)
705 return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
713 typedescription_t *td;
714 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
716 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
718 pContext->LocalToString(params[3], &prop);
719 if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
721 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
723 if (td->fieldType != FIELD_CHARACTER)
725 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
727 offset = td->fieldOffset[TD_OFFSET_NORMAL];
728 maxlen = td->fieldSize;
734 IServerNetworkable *pNet = pEdict->GetNetworkable();
737 return pContext->ThrowNativeError("The edict is not networkable");
739 pContext->LocalToString(params[3], &prop);
740 SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
743 return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
745 if (pSend->GetType() != DPT_String)
747 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
749 offset = pSend->GetOffset();
750 maxlen = DT_MAX_STRING_BUFFERSIZE;
756 return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
761 char *dest = (char *)((uint8_t *)pEntity + offset);
763 pContext->LocalToString(params[4], &src);
764 size_t len = strncopy(dest, src, maxlen);
768 g_HL2.SetEdictStateChanged(pEdict, offset);
774 REGISTER_NATIVES(entityNatives)
776 {"ChangeEdictState", ChangeEdictState},
777 {"CreateEdict", CreateEdict},
778 {"FindSendPropOffs", FindSendPropOffs},
779 {"GetEdictClassname", GetEdictClassname},
780 {"GetEdictFlags", GetEdictFlags},
781 {"GetEntData", GetEntData},
782 {"GetEntDataEnt", GetEntDataEnt},
783 {"GetEntDataFloat", GetEntDataFloat},
784 {"GetEntDataVector", GetEntDataVector},
785 {"GetEntityCount", GetEntityCount},
786 {"GetEntityNetClass", GetEntityNetClass},
787 {"GetMaxEntities", GetMaxEntities},
788 {"IsEntNetworkable", IsEntNetworkable},
789 {"IsValidEdict", IsValidEdict},
790 {"IsValidEntity", IsValidEntity},
791 {"RemoveEdict", RemoveEdict},
792 {"SetEdictFlags", SetEdictFlags},
793 {"SetEntData", SetEntData},
794 {"SetEntDataEnt", SetEntDataEnt},
795 {"SetEntDataFloat", SetEntDataFloat},
796 {"SetEntDataVector", SetEntDataVector},
797 {"FindDataMapOffs", FindDataMapOffs},
798 {"GetEntDataString", GetEntDataString},
799 {"SetEntDataString", SetEntDataString},
800 {"GetEntPropString", GetEntPropString},
801 {"SetEntPropString", SetEntPropString},