//----------------------------------------------------------------------------- // Calls all callables for the command when it is called on the server. //----------------------------------------------------------------------------- void CServerCommandManager::Dispatch( const CCommand& command ) { // Loop through all registered callbacks for the command // (use equals also to know when to call the old callback) for(int i = 0; i <= m_vecCallables.Count(); i++) { // Is the current iteration for a registered callback? if( i < m_vecCallables.Count() ) { BEGIN_BOOST_PY() // Get the PyObject instance of the callable PyObject* pCallable = m_vecCallables[i].ptr(); // Call the callable and store its return value object returnValue = CALL_PY_FUNC(pCallable, boost::ref(command)); // Does the callable wish to block the command? if( !returnValue.is_none() && extract<int>(returnValue) == (int) BLOCK) { // Block the command break; } END_BOOST_PY_NORET() } // Was the command previously registered? else if(m_pOldCommand)
//----------------------------------------------------------------------------- // Calls all callables for the command when it is called on the client. //----------------------------------------------------------------------------- CommandReturn CClientCommandManager::Dispatch( const CCommand& command, int iIndex ) { // Loop through all callables registered for the CClientCommandManager instance for(int i = 0; i < m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() // Get the PyObject instance of the callable PyObject* pCallable = m_vecCallables[i].ptr(); // Call the callable and store its return value object returnValue = CALL_PY_FUNC(pCallable, boost::ref(command), iIndex); // Does the callable wish to block the command? if( !returnValue.is_none() && extract<int>(returnValue) == (int) BLOCK) { // Block the command return BLOCK; } END_BOOST_PY_NORET() } return CONTINUE; }
//----------------------------------------------------------------------------- // Notifies all registered callbacks. //----------------------------------------------------------------------------- void CListenerManager::Notify(tuple args, dict kwargs) { static object callback_caller = eval("lambda func, args, kwargs: func(*args, **kwargs)"); for(int i = 0; i < m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() callback_caller(m_vecCallables[i], args, kwargs); END_BOOST_PY_NORET() } }
//----------------------------------------------------------------------------- // Calls all registered tick listeners. //----------------------------------------------------------------------------- void CTickListenerManager::call_tick_listeners() { for(int i = 0; i < m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() // Get the PyObject instance of the callable PyObject* pCallable = m_vecCallables[i].ptr(); // Call the callable CALL_PY_FUNC(pCallable); END_BOOST_PY_NORET() } }
//----------------------------------------------------------------------------- // Dispatches a client command. //----------------------------------------------------------------------------- PLUGIN_RESULT DispatchClientCommand(edict_t* pEntity, const CCommand &command) { unsigned int iIndex; if (!IndexFromEdict(pEntity, iIndex)) return PLUGIN_CONTINUE; // Loop through all registered Client Command Filters for(int i = 0; i < s_ClientCommandFilters.m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() // Get the PyObject instance of the callable PyObject* pCallable = s_ClientCommandFilters.m_vecCallables[i].ptr(); // Call the callable and store its return value object returnValue = CALL_PY_FUNC(pCallable, boost::ref(command), iIndex); // Does the Client Command Filter want to block the command? if( !returnValue.is_none() && extract<int>(returnValue) == (int)BLOCK) { // Block the command return PLUGIN_STOP; } END_BOOST_PY_NORET() } // Get the command's name const char* szCommand = command.Arg(0); // Find if the command exists in the mapping ClientCommandMap::iterator commandMapIter = g_ClientCommandMap.find(szCommand); if( commandMapIter != g_ClientCommandMap.end() ) { // If the command exists, get the CClientCommandManager instance and call its Dispatch method CClientCommandManager* pCClientCommandManager = commandMapIter->second; // Does the command need to be blocked? if( !pCClientCommandManager->Dispatch(command, iIndex)) { // Block the command return PLUGIN_STOP; } } return PLUGIN_CONTINUE; }
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage ) { extern CListenerManager* GetOnServerOutputListenerManager(); bool block = false; for(int i = 0; i < GetOnServerOutputListenerManager()->m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() object return_value = CALL_PY_FUNC( GetOnServerOutputListenerManager()->m_vecCallables[i].ptr(), (MessageSeverity) pContext->m_Severity, pMessage); if (!return_value.is_none() && extract<OutputReturn>(return_value) == OUTPUT_BLOCK) block = true; END_BOOST_PY_NORET() } if (!block) { // Restore the old logging state before SP has been loaded LoggingSystem_PopLoggingState(false); // Resend the log message. Our listener won't get called anymore LoggingSystem_LogDirect( pContext->m_ChannelID, pContext->m_Severity, pContext->m_Color, pMessage); // Create a new logging state with only our listener being active #if defined(ENGINE_LEFT4DEAD2) LoggingSystem_PushLoggingState(false); #else LoggingSystem_PushLoggingState(false, true); #endif LoggingSystem_RegisterLoggingListener(this); } }
SpewRetval_t SP_SpewOutput( SpewType_t spewType, const tchar *pMsg ) { extern CListenerManager* GetOnServerOutputListenerManager(); bool block = false; for(int i = 0; i < GetOnServerOutputListenerManager()->m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() object return_value = CALL_PY_FUNC( GetOnServerOutputListenerManager()->m_vecCallables[i].ptr(), (MessageSeverity) spewType, pMsg); if (!return_value.is_none() && extract<OutputReturn>(return_value) == OUTPUT_BLOCK) block = true; END_BOOST_PY_NORET() } if (!block && g_SourcePythonPlugin.m_pOldSpewOutputFunc) return g_SourcePythonPlugin.m_pOldSpewOutputFunc(spewType, pMsg); return SPEW_CONTINUE; }
//--------------------------------------------------------------------------------- // Initializes python. //--------------------------------------------------------------------------------- bool CPythonManager::Initialize( void ) { // Construct a path to the python engine directory. char szPythonHome[MAX_GAME_PATH]; V_snprintf(szPythonHome, MAX_GAME_PATH, "%s/Python3", g_GamePaths.GetSPDir()); V_FixSlashes(szPythonHome); DevMsg(1, "[SP] Python home path set to %s\n", szPythonHome); // Convert to wide char for python. wchar_t wszPythonHome[1024]; V_strtowcs(szPythonHome, -1, wszPythonHome, 1024); // Set that as the python home directory. Py_SetPythonHome(wszPythonHome); Py_SetProgramName(wszPythonHome); Py_SetPath(wszPythonHome); // Initialize python and its namespaces. Py_Initialize(); // Print some information DevMsg(1, "Python version %s initialized!\n", Py_GetVersion()); // Make sure sys is imported. PyRun_SimpleString("import sys"); // Add the Python API path. AddToSysPath("/packages/source-python"); // Add operating system specific paths. #if defined(WIN32) AddToSysPath("/Python3/plat-win"); #else AddToSysPath("/Python3/plat-linux"); // We've got a bunch of linux shared objects here we need to load. AddToSysPath("/Python3/lib-dynload"); #endif // Site packages for any extra packages... AddToSysPath("/packages/site-packages"); // Add the custom packages path. AddToSysPath("/packages/custom"); // And of course, the plugins directory for script imports. AddToSysPath("/plugins"); // Initialize all converters InitConverters(); // Initialize all submodules modulsp_init(); // Import the main module file. DevMsg(1, "[SP] Importing main module..\n"); BEGIN_BOOST_PY() python::import("__init__"); END_BOOST_PY_NORET(); // Noret because we have more stuff to do after this import. DevMsg(0, "[Source.Python] Loaded successfully.\n"); return true; }
//----------------------------------------------------------------------------- // Dispatches the say and say_team commands. //----------------------------------------------------------------------------- void SayConCommand::Dispatch( const CCommand& command ) { // This is the case if just "say" or "say_team" was entered into the server if (command.ArgC() == 1) return; // Get the index of the player that used the command int iIndex = GetCommandIndex(); // Get the IPlayerInfo instance of the player IPlayerInfo* pPlayerInfo = PlayerInfoFromIndex(iIndex); // Get whether the command was say or say_team bool bTeamOnly = strcmp(command.Arg(0), "say_team") == 0; // Loop through all registered Say Filter callbacks for(int i = 0; i < s_SayFilters.m_vecCallables.Count(); i++) { BEGIN_BOOST_PY() // Get the PyObject instance of the callable PyObject* pCallable = s_SayFilters.m_vecCallables[i].ptr(); // Call the callable and store its return value object returnValue = CALL_PY_FUNC(pCallable, ptr(pPlayerInfo), bTeamOnly, boost::ref(command)); // Does the current Say Filter wish to block the command? if( !returnValue.is_none() && extract<int>(returnValue) == (int) BLOCK) { // Block the command return; } END_BOOST_PY_NORET() } // Get the name of the command used std::string szCommandString (command.Arg(1)); // Copy the string to get a char instance char * szCopyCommandString = new char [szCommandString.length() + 1]; std::strcpy(szCopyCommandString, szCommandString.c_str()); // Split the command using <space> as the delimiter // This should be the actual Say Command char * szCommand = std::strtok(szCopyCommandString, " "); // Find if the command is registered SayCommandMap::iterator commandMapIter = g_SayCommandMap.find(szCommand); if( commandMapIter != g_SayCommandMap.end() ) { // Get the CSayCommandManager instance for the command CSayCommandManager* pCSayCommandManager = commandMapIter->second; // Call the command and see it wants to block the command if( pCSayCommandManager->Dispatch(pPlayerInfo, bTeamOnly, command) == BLOCK) { // Block the command return; } } // Was the command previously registered? if( m_pOldCommand ) { // Call the old command callback m_pOldCommand->Dispatch(command); } }