static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params) { if (params[1]) { return playerhelpers->GetNumPlayers(); } int maxplayers = playerhelpers->GetMaxClients(); int count = 0; for (int i = 1; i <= maxplayers; ++i) { IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i); if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame())) { count++; } } return (playerhelpers->GetNumPlayers() + count); }
static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params) { int client = params[1]; IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (!pPlayer) { return pContext->ThrowNativeError("Client index %d is invalid", client); } if (!pPlayer->IsConnected()) { return pContext->ThrowNativeError("Client %d is not connected", client); } AdminId id; if ((id = pPlayer->GetAdminId()) == INVALID_ADMIN_ID) { return 0; } return adminsys->GetAdminFlags(id, Access_Effective); }
static cell_t SetUserAdmin(IPluginContext *pContext, const cell_t *params) { int client = params[1]; IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (!pPlayer) { return pContext->ThrowNativeError("Client index %d is invalid", client); } if (!pPlayer->IsConnected()) { return pContext->ThrowNativeError("Client %d is not connected", client); } if (!adminsys->IsValidAdmin(params[2]) && params[2] != INVALID_ADMIN_ID) { return pContext->ThrowNativeError("AdminId %x is invalid", params[2]); } pPlayer->SetAdminId(params[2], params[3] ? true : false); return 1; }
static cell_t sm_GetStatCell(IPluginContext *pContext, const cell_t *params) { ISteamGameServerStats *pStats = GetServerStatsPointer(); if (pStats == NULL) { return 0; } int client = gamehelpers->ReferenceToIndex(params[1]); IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (pPlayer == NULL || pPlayer->IsConnected() == false) { return pContext->ThrowNativeError("Client index %d is invalid", params[1]); } char *pName; pContext->LocalToString(params[2], &pName); cell_t *pValue; pContext->LocalToPhysAddr(params[3], &pValue); CSteamID checkid = CreateCommonCSteamID(pPlayer, params, 4, 5); return pStats->GetUserStat(checkid, pName, pValue) ? 1 : 0; }
DataStatus DecodeValveParam(IPluginContext *pContext, cell_t param, const ValveCall *pCall, const ValvePassInfo *data, void *_buffer) { void *buffer = (unsigned char *)_buffer + data->offset; switch (data->vtype) { case Valve_Vector: { cell_t *addr; int err; err = pContext->LocalToPhysAddr(param, &addr); unsigned char *mem = (unsigned char *)buffer; if (data->type == PassType_Basic) { /* Store the object in the next N bytes, and store * a pointer to that object right beforehand. */ Vector **realPtr = (Vector **)buffer; if (addr == pContext->GetNullRef(SP_NULL_VECTOR)) { if (data->decflags & VDECODE_FLAG_ALLOWNULL) { *realPtr = NULL; return Data_Okay; } else { pContext->ThrowNativeError("NULL not allowed"); return Data_Fail; } } else { mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset; *realPtr = (Vector *)mem; } } if (err != SP_ERROR_NONE) { pContext->ThrowNativeErrorEx(err, "Could not read plugin data"); return Data_Fail; } /* Use placement new to initialize the object cleanly * This has no destructor so we don't need to do * DestroyValveParam() or something :] */ Vector *v = new (mem) Vector( sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])); return Data_Okay; } case Valve_QAngle: { cell_t *addr; int err; err = pContext->LocalToPhysAddr(param, &addr); unsigned char *mem = (unsigned char *)buffer; if (data->type == PassType_Basic) { /* Store the object in the next N bytes, and store * a pointer to that object right beforehand. */ QAngle **realPtr = (QAngle **)buffer; if (addr == pContext->GetNullRef(SP_NULL_VECTOR)) { if (!(data->decflags & VDECODE_FLAG_ALLOWNULL)) { pContext->ThrowNativeError("NULL not allowed"); return Data_Fail; } else { *realPtr = NULL; return Data_Okay; } } else { mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset; *realPtr = (QAngle *)mem; } } if (err != SP_ERROR_NONE) { pContext->ThrowNativeErrorEx(err, "Could not read plugin data"); return Data_Fail; } /* Use placement new to initialize the object cleanly * This has no destructor so we don't need to do * DestroyValveParam() or something :] */ QAngle *v = new (mem) QAngle( sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])); return Data_Okay; } case Valve_CBasePlayer: { CBaseEntity *pEntity = NULL; if (data->decflags & VDECODE_FLAG_BYREF) { cell_t *addr; pContext->LocalToPhysAddr(param, &addr); param = *addr; } int index = gamehelpers->ReferenceToIndex(param); if ((unsigned)index == INVALID_EHANDLE_INDEX && param != -1) { return Data_Fail; } if (index >= 1 && index <= playerhelpers->GetMaxClients()) { IGamePlayer *player = playerhelpers->GetGamePlayer(index); if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsConnected()) { pContext->ThrowNativeError("Client %d is not connected", param); return Data_Fail; } else if (!player->IsInGame()) { pContext->ThrowNativeError("Client %d is not in game", param); return Data_Fail; } pEntity = gamehelpers->ReferenceToEntity(param); } else if (param == -1) { if (data->decflags & VDECODE_FLAG_ALLOWNULL) { pEntity = NULL; } else { pContext->ThrowNativeError("NULL not allowed"); return Data_Fail; } } else { pContext->ThrowNativeError("Entity index %d is not a valid client", param); return Data_Fail; } CBaseEntity **ebuf = (CBaseEntity **)buffer; *ebuf = pEntity; return Data_Okay; } case Valve_CBaseEntity: { CBaseEntity *pEntity = NULL; if (data->decflags & VDECODE_FLAG_BYREF) { cell_t *addr; pContext->LocalToPhysAddr(param, &addr); param = *addr; } int index = gamehelpers->ReferenceToIndex(param); if ((unsigned)index == INVALID_EHANDLE_INDEX && param != -1) { return Data_Fail; } if (index >= 1 && index <= playerhelpers->GetMaxClients()) { IGamePlayer *player = playerhelpers->GetGamePlayer(index); if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsConnected()) { pContext->ThrowNativeError("Client %d is not connected", param); return Data_Fail; } else if (!player->IsInGame()) { pContext->ThrowNativeError("Client %d is not in game", param); return Data_Fail; } pEntity = gamehelpers->ReferenceToEntity(param); } else if (param == -1) { if (data->decflags & VDECODE_FLAG_ALLOWNULL) { pEntity = NULL; } else { pContext->ThrowNativeError("NULL not allowed"); return Data_Fail; } } else if (index == 0) { if (data->decflags & VDECODE_FLAG_ALLOWWORLD) { pEntity = gamehelpers->ReferenceToEntity(0); } else { pContext->ThrowNativeError("World not allowed"); return Data_Fail; } } else { pEntity = gamehelpers->ReferenceToEntity(param); if (!pEntity) { pContext->ThrowNativeError("Entity %d is not valid", param); return Data_Fail; } } CBaseEntity **ebuf = (CBaseEntity **)buffer; *ebuf = pEntity; return Data_Okay; } case Valve_Edict: { edict_t *pEdict; if (data->decflags & VDECODE_FLAG_BYREF) { cell_t *addr; pContext->LocalToPhysAddr(param, &addr); param = *addr; } if (param >= 1 && param <= playerhelpers->GetMaxClients()) { IGamePlayer *player = playerhelpers->GetGamePlayer(param); if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsConnected()) { pContext->ThrowNativeError("Client %d is not connected", param); return Data_Fail; } else if (!player->IsInGame()) { pContext->ThrowNativeError("Client %d is not in game", param); return Data_Fail; } pEdict = player->GetEdict(); } else if (param == -1) { if (data->decflags & VDECODE_FLAG_ALLOWNULL) { pEdict = NULL; } else { pContext->ThrowNativeError("NULL not allowed"); return Data_Fail; } } else if (param == 0) { if (data->decflags & VDECODE_FLAG_ALLOWWORLD) { pEdict = PEntityOfEntIndex(0); } else { pContext->ThrowNativeError("World not allowed"); return Data_Fail; } } else { pEdict = PEntityOfEntIndex(param); if (!pEdict || pEdict->IsFree()) { pContext->ThrowNativeError("Entity %d is not valid or is freed", param); return Data_Fail; } } edict_t **ebuf = (edict_t **)buffer; *ebuf = pEdict; return Data_Okay; } case Valve_POD: case Valve_Float: { if (data->decflags & VDECODE_FLAG_BYREF) { cell_t *addr; pContext->LocalToPhysAddr(param, &addr); param = *addr; } if (data->flags & PASSFLAG_ASPOINTER) { *(void **)buffer = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset; buffer = *(void **)buffer; } *(cell_t *)buffer = param; return Data_Okay; } case Valve_Bool: { if (data->decflags & VDECODE_FLAG_BYREF) { cell_t *addr; pContext->LocalToPhysAddr(param, &addr); param = *addr; } if (data->flags & PASSFLAG_ASPOINTER) { *(bool **)buffer = (bool *)((unsigned char *)_buffer + pCall->stackEnd + data->obj_offset); buffer = *(bool **)buffer; } *(bool *)buffer = param ? true : false; return Data_Okay; } case Valve_String: { char *addr; pContext->LocalToString(param, &addr); *(char **)buffer = addr; return Data_Okay; } } return Data_Fail; }
static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params) { if (iserver == NULL) { return pContext->ThrowNativeError("IServer interface not supported, file a bug report."); } IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); IClient *pClient = iserver->GetClient(params[1] - 1); if (player == NULL || pClient == NULL) { return pContext->ThrowNativeError("Invalid client index %d", params[1]); } if (!player->IsConnected()) { return pContext->ThrowNativeError("Client %d is not connected", params[1]); } static ValveCall *pCall = NULL; if (!pCall) { ValvePassInfo params[2]; InitPass(params[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL); InitPass(params[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL); if (!CreateBaseCall("SetUserCvar", ValveCall_Entity, NULL, params, 2, &pCall)) { return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod"); } else if (!pCall) { return pContext->ThrowNativeError("\"SetUserCvar\" wrapper failed to initialized"); } } /* TODO: Use UpdateUserSettings function for all engines */ #if SOURCE_ENGINE == SE_DARKMESSIAH static ValveCall *pUpdateSettings = NULL; if (!pUpdateSettings) { if (!CreateBaseCall("UpdateUserSettings", ValveCall_Entity, NULL, NULL, 0, &pUpdateSettings)) { return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod"); } else if (!pUpdateSettings) { return pContext->ThrowNativeError("\"SetUserCvar\" wrapper failed to initialized"); } } #else static int changedOffset = -1; if (changedOffset == -1) { if (!g_pGameConf->GetOffset("InfoChanged", &changedOffset)) { return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod"); } } #endif unsigned char *CGameClient = (unsigned char *)pClient - 4; START_CALL(); /* Not really a CBaseEntity* but this works */ CBaseEntity **ebuf = (CBaseEntity **)vptr; *ebuf = (CBaseEntity *)CGameClient; DECODE_VALVE_PARAM(2, vparams, 0); DECODE_VALVE_PARAM(3, vparams, 1); FINISH_CALL_SIMPLE(NULL); #if SOURCE_ENGINE == SE_DARKMESSIAH unsigned char *args = pUpdateSettings->stk_get(); *(void **)args = CGameClient; pUpdateSettings->call->Execute(args, NULL); pUpdateSettings->stk_put(args); #else uint8_t* changed = (uint8_t *)(CGameClient + changedOffset); *changed = 1; #endif return 1; }
static cell_t SteamIdToLocal(IPluginContext *pCtx, int index, AuthIdType authType, cell_t local_addr, size_t bytes, bool validate) { pCtx->StringToLocal(local_addr, bytes, "STEAM_ID_STOP_IGNORING_RETVALS"); if ((index < 1) || (index > playerhelpers->GetMaxClients())) { return pCtx->ThrowNativeError("Client index %d is invalid", index); } IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index); if (!pPlayer->IsConnected()) { return pCtx->ThrowNativeError("Client %d is not connected", index); } const char *authstr; switch (authType) { case AuthIdType::Engine: authstr = pPlayer->GetAuthString(validate); if (!authstr || authstr[0] == '\0') { return 0; } pCtx->StringToLocal(local_addr, bytes, authstr); break; case AuthIdType::Steam2: authstr = pPlayer->GetSteam2Id(validate); if (!authstr || authstr[0] == '\0') { return 0; } pCtx->StringToLocal(local_addr, bytes, authstr); break; case AuthIdType::Steam3: authstr = pPlayer->GetSteam3Id(validate); if (!authstr || authstr[0] == '\0') { return 0; } pCtx->StringToLocal(local_addr, bytes, authstr); break; case AuthIdType::SteamId64: { if (pPlayer->IsFakeClient() || gamehelpers->IsLANServer()) { return 0; } uint64_t steamId = pPlayer->GetSteamId64(validate); if (steamId == 0) { return 0; } char szAuth[64]; snprintf(szAuth, sizeof(szAuth), "%" PRIu64, steamId); pCtx->StringToLocal(local_addr, bytes, szAuth); } break; } return 1; }
static cell_t FormatActivitySource(IPluginContext *pContext, const cell_t *params) { int value; int client; int target; IGamePlayer *pTarget; AdminId aidTarget; const char *identity[2] = { "Console", "ADMIN" }; client = params[1]; target = params[2]; if ((pTarget = playerhelpers->GetGamePlayer(target)) == NULL) { return pContext->ThrowNativeError("Invalid client index %d", target); } if (!pTarget->IsConnected()) { return pContext->ThrowNativeError("Client %d not connected", target); } value = bridge->GetActivityFlags(); if (client != 0) { IGamePlayer *pPlayer; if ((pPlayer = playerhelpers->GetGamePlayer(client)) == NULL) { return pContext->ThrowNativeError("Invalid client index %d", client); } if (!pPlayer->IsConnected()) { return pContext->ThrowNativeError("Client %d not connected", client); } identity[0] = pPlayer->GetName(); AdminId id = pPlayer->GetAdminId(); if (id == INVALID_ADMIN_ID || !adminsys->GetAdminFlag(id, Admin_Generic, Access_Effective)) { identity[1] = "PLAYER"; } } int mode = 1; bool bShowActivity = false; if ((aidTarget = pTarget->GetAdminId()) == INVALID_ADMIN_ID || !adminsys->GetAdminFlag(aidTarget, Admin_Generic, Access_Effective)) { /* Treat this as a normal user */ if ((value & kActivityNonAdmins) || (value & kActivityNonAdminsNames)) { if ((value & 2) || (target == client)) { mode = 0; } bShowActivity = true; } } else { /* Treat this as an admin user */ bool is_root = adminsys->GetAdminFlag(aidTarget, Admin_Root, Access_Effective); if ((value & kActivityAdmins) || (value & kActivityAdminsNames) || ((value & kActivityRootNames) && is_root)) { if ((value & kActivityAdminsNames) || ((value & kActivityRootNames) && is_root) || (target == client)) { mode = 0; } bShowActivity = true; } } /* Otherwise, send it back to the script. */ pContext->StringToLocalUTF8(params[3], params[4], identity[mode], NULL); return bShowActivity ? 1 : 0; }
static cell_t _ShowActivity2(IPluginContext *pContext, const cell_t *params, const char *tag, cell_t fmt_param) { char message[255]; char buffer[255]; int value = bridge->GetActivityFlags(); unsigned int replyto = playerhelpers->GetReplyTo(); int client = params[1]; const char *name = "Console"; const char *sign = "ADMIN"; if (client != 0) { IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (!pPlayer || !pPlayer->IsConnected()) { return pContext->ThrowNativeError("Client index %d is invalid", client); } name = pPlayer->GetName(); AdminId id = pPlayer->GetAdminId(); if (id == INVALID_ADMIN_ID || !adminsys->GetAdminFlag(id, Admin_Generic, Access_Effective)) { sign = "PLAYER"; } g_pSM->SetGlobalTarget(client); { DetectExceptions eh(pContext); g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param); if (eh.HasException()) return 0; } /* We don't display directly to the console because the chat text * simply gets added to the console, so we don't want it to print * twice. */ g_pSM->Format(message, sizeof(message), "%s%s", tag, buffer); gamehelpers->TextMsg(client, TEXTMSG_DEST_CHAT, message); } else { g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); { DetectExceptions eh(pContext); g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param); if (eh.HasException()) return 0; } g_pSM->Format(message, sizeof(message), "%s%s\n", tag, buffer); bridge->ConPrint(message); } if (value == kActivityNone) { return 1; } int maxClients = playerhelpers->GetMaxClients(); for (int i = 1; i <= maxClients; i++) { IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i); if (!pPlayer->IsInGame() || pPlayer->IsFakeClient() || i == client) { continue; } AdminId id = pPlayer->GetAdminId(); g_pSM->SetGlobalTarget(i); if (id == INVALID_ADMIN_ID || !adminsys->GetAdminFlag(id, Admin_Generic, Access_Effective)) { /* Treat this as a normal user */ if ((value & kActivityNonAdmins) || (value & kActivityNonAdminsNames)) { const char *newsign = sign; if ((value & kActivityNonAdminsNames)) { newsign = name; } { DetectExceptions eh(pContext); g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param); if (eh.HasException()) return 0; } g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer); gamehelpers->TextMsg(i, TEXTMSG_DEST_CHAT, message); } } else { /* Treat this as an admin user */ bool is_root = adminsys->GetAdminFlag(id, Admin_Root, Access_Effective); if ((value & kActivityAdmins) || (value & kActivityAdminsNames) || ((value & kActivityRootNames) && is_root)) { const char *newsign = sign; if ((value & kActivityAdminsNames) || ((value & kActivityRootNames) && is_root)) { newsign = name; } { DetectExceptions eh(pContext); g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, fmt_param); if (eh.HasException()) return 0; } g_pSM->Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer); gamehelpers->TextMsg(i, TEXTMSG_DEST_CHAT, message); } } } return 1; }