X Tutup
/** * ============================================================================= * Source Python * Copyright (C) 2012-2018 Source Python Development Team. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . * * As a special exception, the Source Python Team gives you permission * to link the code of this program (as well as its derivative works) to * "Half-Life 2," the "Source Engine," and any Game MODs that run on software * by the Valve Corporation. You must obey the GNU General Public License in * all respects for all other code used. Additionally, the Source.Python * Development Team grants this exception to all derivative works. */ //--------------------------------------------------------------------------------- // Includes //--------------------------------------------------------------------------------- class CBasePlayer; // Boost.Python #include "boost/python.hpp" using namespace boost::python; // SDK #include "edict.h" #include "game/shared/shareddefs.h" #include "game/shared/usercmd.h" // Source.Python #include "sp_hooks.h" #include "utilities/conversions.h" #include "utilities/call_python.h" #include "modules/entities/entities_entity.h" #include "modules/listeners/listeners_manager.h" //--------------------------------------------------------------------------------- // GLOBAL VARIABLES //--------------------------------------------------------------------------------- std::vector g_EntityHooks; //--------------------------------------------------------------------------------- // ISimpleEntityHook //--------------------------------------------------------------------------------- ISimpleEntityHook::ISimpleEntityHook(const char* func_name, HookHandlerFn* hook_handler, HookType_t hook_type) { this->func_name = func_name; this->hook_handler = hook_handler; this->hook_type = hook_type; } bool ISimpleEntityHook::Initialize(CBaseEntity* pEntity) { if (!Test(pEntity)) { return false; } PythonLog(4, "Initializing core hook (%s)...", this->func_name); unsigned int index; if (!IndexFromBaseEntity(pEntity, index)) { PythonLog(0, "Failed to convert the entity pointer to an index (%s)", this->func_name); return true; } CFunction* func = NULL; try { static object Entity = import("entities.entity").attr("Entity"); object entity = Entity(index); func = extract(entity.attr(this->func_name)); } catch (...) { PyErr_Print(); PyErr_Clear(); PythonLog(0, "Failed to import entities.entity.Entity or to retrieve %s.", this->func_name); return true; } if (!func->AddHook(this->hook_type, this->hook_handler)) { PythonLog(0, "Could not create a hook for %s.", this->func_name); return true; } PythonLog(3, "Core hook (%s) has been initialized.", this->func_name); return true; } //--------------------------------------------------------------------------------- // PlayerHook //--------------------------------------------------------------------------------- PlayerHook::PlayerHook(const char* func_name, HookHandlerFn* hook_handler, HookType_t hook_type) :ISimpleEntityHook(func_name, hook_handler, hook_type) { } bool PlayerHook::Test(CBaseEntity* pEntity) { CBaseEntityWrapper* pWrapper = (CBaseEntityWrapper*) pEntity; return pWrapper->IsPlayer(); } //--------------------------------------------------------------------------------- // FUNCTIONS //--------------------------------------------------------------------------------- void InitHooks() { CBaseEntity* pEntity = (CBaseEntity *) servertools->FirstEntity(); while (pEntity) { InitHooks(pEntity); pEntity = (CBaseEntity *) servertools->NextEntity(pEntity); } } void InitHooks(CBaseEntity* pEntity) { if (!pEntity) return; std::vector::iterator it = g_EntityHooks.begin(); while (it != g_EntityHooks.end()) { IEntityHook* pHook = *it; if (pHook->Initialize(pEntity)) { it = g_EntityHooks.erase(it); delete pHook; } else { ++it; } } } //--------------------------------------------------------------------------------- // HOOKS //--------------------------------------------------------------------------------- bool PrePlayerRunCommand(HookType_t hook_type, CHook* pHook) { bool bUsePreRegister; if (hook_type == HOOKTYPE_PRE) { GET_LISTENER_MANAGER(OnPlayerRunCommand, run_command_manager); GET_LISTENER_MANAGER(OnButtonStateChanged, button_state_manager); if (!run_command_manager->GetCount() && !button_state_manager->GetCount()) return false; } else { bUsePreRegister = pHook->m_bUsePreRegisters; pHook->m_bUsePreRegisters = true; GET_LISTENER_MANAGER(OnPlayerPostRunCommand, post_run_command_manager); if (!post_run_command_manager->GetCount()) return false; } static object Player = import("players.entity").attr("Player"); CBaseEntity* pEntity = pHook->GetArgument(0); unsigned int index; if (!IndexFromBaseEntity(pEntity, index)) return false; // https://github.com/Source-Python-Dev-Team/Source.Python/issues/149 #if defined(ENGINE_BRANCH_TF2) CUserCmd cmd = *pHook->GetArgument(1); CUserCmd* pCmd = &cmd; #else CUserCmd* pCmd = pHook->GetArgument(1); #endif object player = Player(index); if (hook_type == HOOKTYPE_PRE) { CALL_LISTENERS(OnPlayerRunCommand, player, ptr(pCmd)); GET_LISTENER_MANAGER(OnButtonStateChanged, button_state_manager); if (button_state_manager->GetCount()) { CBaseEntityWrapper* pWrapper = (CBaseEntityWrapper*) pEntity; static int offset = pWrapper->FindDatamapPropertyOffset("m_nButtons"); int buttons = pWrapper->GetDatamapPropertyByOffset(offset); if (buttons != pCmd->buttons) { CALL_LISTENERS(OnButtonStateChanged, player, buttons, pCmd->buttons); } } } else { CALL_LISTENERS(OnPlayerPostRunCommand, player, ptr(pCmd)); } #if defined(ENGINE_BRANCH_TF2) CUserCmd* pRealCmd = pHook->GetArgument(1); memcpy(pRealCmd, pCmd, sizeof(CUserCmd)); #endif if (hook_type == HOOKTYPE_POST) { pHook->m_bUsePreRegisters = bUsePreRegister; } return false; }
X Tutup