From 76e3b5ae3021cc1365f300b0952d7adbb5fbdb4f Mon Sep 17 00:00:00 2001 From: Ayuto Date: Sun, 15 Nov 2020 13:08:15 +0100 Subject: [PATCH 1/9] Add back game rules --- .../developing/modules/engines.gamerules.rst | 7 + .../source-python/engines/gamerules.py | 79 ++++++++++ src/CMakeLists.txt | 1 + .../engines/engines_gamerules_wrap.cpp | 137 ++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 addons/source-python/docs/source-python/source/developing/modules/engines.gamerules.rst create mode 100644 addons/source-python/packages/source-python/engines/gamerules.py create mode 100644 src/core/modules/engines/engines_gamerules_wrap.cpp diff --git a/addons/source-python/docs/source-python/source/developing/modules/engines.gamerules.rst b/addons/source-python/docs/source-python/source/developing/modules/engines.gamerules.rst new file mode 100644 index 000000000..dfd7985cf --- /dev/null +++ b/addons/source-python/docs/source-python/source/developing/modules/engines.gamerules.rst @@ -0,0 +1,7 @@ +engines.gamerules module +========================= + +.. automodule:: engines.gamerules + :members: + :undoc-members: + :show-inheritance: diff --git a/addons/source-python/packages/source-python/engines/gamerules.py b/addons/source-python/packages/source-python/engines/gamerules.py new file mode 100644 index 000000000..f541991e6 --- /dev/null +++ b/addons/source-python/packages/source-python/engines/gamerules.py @@ -0,0 +1,79 @@ +# ../engines/gamerules.py + +"""Provides access to the gamerules instance.""" + +# ============================================================================= +# >> IMPORTS +# ============================================================================= +# Source.Python Imports +# Memory +from memory import make_object +# Entities +from entities.entity import BaseEntity +from entities.factories import factory_dictionary + + +# ============================================================================= +# >> FORWARD IMPORTS +# ============================================================================= +# Source.Python Imports +# Engines +from _engines._gamerules import GameSystem +from _engines._gamerules import GameSystemPerFrame +from _engines._gamerules import BaseGameSystemPerFrame +from _engines._gamerules import AutoGameSystemPerFrame +from _engines._gamerules import GameRules + + +# ============================================================================= +# >> ALL DECLARATION +# ============================================================================= +__all__ = ( + 'AutoGameSystemPerFrame', + 'BaseGameSystemPerFrame', + 'GameSystem', + 'GameSystemPerFrame', + 'find_game_rules', + 'find_game_rules_proxy_name',) + + +# ============================================================================= +# >> FUNCTIONS +# ============================================================================= +def find_game_rules_proxy_name(): + """Find the entity name that proxies the game rules (e. g. + ``cs_gamerules``). + + :raise ValueError: + Raised if the game rules proxy name wasn't found. + :rtype: str + """ + for classname in factory_dictionary: + if 'gamerules' not in classname: + continue + + return classname + + raise ValueError('Unable to find game rules proxy name.') + +def find_game_rules(): + """Find the game rules instance. + + :raise ValueError: + Raised if the game rules instance wasn't found. + :rtype: GameRules + """ + proxy = BaseEntity.find_or_create(find_game_rules_proxy_name()) + cls = proxy.server_class + while cls: + for prop in cls.table: + if 'gamerules_data' not in prop.name: + continue + + return make_object( + GameRules, + prop.data_table_proxy_function(None, None, None, None, 0)) + + cls = cls.next + + raise ValueError('Unable to find game rules.') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6df2fd77..e50f4afdd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -203,6 +203,7 @@ Set(SOURCEPYTHON_ENGINES_MODULE_SOURCES core/modules/engines/engines_server_wrap.cpp core/modules/engines/engines_sound_wrap.cpp core/modules/engines/engines_trace_wrap.cpp + core/modules/engines/engines_gamerules_wrap.cpp ) # ------------------------------------------------------------------ diff --git a/src/core/modules/engines/engines_gamerules_wrap.cpp b/src/core/modules/engines/engines_gamerules_wrap.cpp new file mode 100644 index 000000000..e0a8b4fae --- /dev/null +++ b/src/core/modules/engines/engines_gamerules_wrap.cpp @@ -0,0 +1,137 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2015 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. +//--------------------------------------------------------------------------------- +// Source.Python +#include "export_main.h" +#include "sp_main.h" + +// SDK +#include "game/shared/gamerules.h" + + +//--------------------------------------------------------------------------------- +// Forward declarations. +//--------------------------------------------------------------------------------- +void export_game_system(scope); +void export_game_system_per_frame(scope); +void export_base_game_system_per_frame(scope); +void export_auto_game_system_per_frame(scope); +void export_game_rules(scope); + + +//--------------------------------------------------------------------------------- +// Declare the _sound module. +//--------------------------------------------------------------------------------- +DECLARE_SP_SUBMODULE(_engines, _gamerules) +{ + export_game_system(_gamerules); + export_game_system_per_frame(_gamerules); + export_base_game_system_per_frame(_gamerules); + export_auto_game_system_per_frame(_gamerules); + export_game_rules(_gamerules); +} + + +//----------------------------------------------------------------------------- +// Expose GameSystem. +//----------------------------------------------------------------------------- +void export_game_system(scope _gamerules) +{ + class_ GameSystem("GameSystem", no_init); + + GameSystem.add_property( + "name", + &IGameSystem::Name); + + GameSystem ADD_MEM_TOOLS(IGameSystem); +} + + +//----------------------------------------------------------------------------- +// Expose GameSystemPerFrame. +//----------------------------------------------------------------------------- +void export_game_system_per_frame(scope _gamerules) +{ + class_, boost::noncopyable> GameSystemPerFrame("GameSystemPerFrame", no_init); + + GameSystemPerFrame ADD_MEM_TOOLS(IGameSystemPerFrame); +} + + +//----------------------------------------------------------------------------- +// Expose BaseGameSystemPerFrame. +//----------------------------------------------------------------------------- +void export_base_game_system_per_frame(scope _gamerules) +{ + class_, boost::noncopyable> BaseGameSystemPerFrame("BaseGameSystemPerFrame", no_init); + + BaseGameSystemPerFrame ADD_MEM_TOOLS(CBaseGameSystemPerFrame); +} + + +//----------------------------------------------------------------------------- +// Expose AutoGameSystemPerFrame. +//----------------------------------------------------------------------------- +void export_auto_game_system_per_frame(scope _gamerules) +{ + class_, boost::noncopyable> AutoGameSystemPerFrame("AutoGameSystemPerFrame", no_init); + + AutoGameSystemPerFrame.add_property( + "next", + make_getter(&CAutoGameSystemPerFrame::m_pNext, reference_existing_object_policy())); + + AutoGameSystemPerFrame ADD_MEM_TOOLS(CAutoGameSystemPerFrame); +} + + +//----------------------------------------------------------------------------- +// Expose GameRules. +//----------------------------------------------------------------------------- +void export_game_rules(scope _gamerules) +{ + class_, boost::noncopyable> GameRules("GameRules", no_init); + + GameRules.add_property( + "game_description", + &CGameRules::GetGameDescription); + + GameRules.def( + "should_collide", + &CGameRules::ShouldCollide); + + GameRules.def( + "get_tagged_convar_list", + &CGameRules::GetTaggedConVarList); + + GameRules ADD_MEM_TOOLS(CGameRules); + + BEGIN_CLASS_INFO(CGameRules) + FUNCTION_INFO(DeathNotice) + END_CLASS_INFO() +} From 3a9bcb37f240f24f4bb24fe2147d10fb4e193a3c Mon Sep 17 00:00:00 2001 From: Ayuto Date: Sun, 15 Nov 2020 17:20:42 +0100 Subject: [PATCH 2/9] Initial commit Since the Linux build doesn't like running with opaque types, I had to change back a lot... --- .../source-python/engines/gamerules.py | 63 +--- src/CMakeLists.txt | 2 + .../modules/engines/engines_gamerules.cpp | 130 +++++++ src/core/modules/engines/engines_gamerules.h | 101 ++++++ .../engines/engines_gamerules_wrap.cpp | 324 ++++++++++++++++-- .../modules/entities/entities_props_wrap.cpp | 3 + 6 files changed, 546 insertions(+), 77 deletions(-) create mode 100644 src/core/modules/engines/engines_gamerules.cpp create mode 100644 src/core/modules/engines/engines_gamerules.h diff --git a/addons/source-python/packages/source-python/engines/gamerules.py b/addons/source-python/packages/source-python/engines/gamerules.py index f541991e6..98400102a 100644 --- a/addons/source-python/packages/source-python/engines/gamerules.py +++ b/addons/source-python/packages/source-python/engines/gamerules.py @@ -18,62 +18,25 @@ # ============================================================================= # Source.Python Imports # Engines -from _engines._gamerules import GameSystem -from _engines._gamerules import GameSystemPerFrame -from _engines._gamerules import BaseGameSystemPerFrame -from _engines._gamerules import AutoGameSystemPerFrame +#from _engines._gamerules import GameSystem +#from _engines._gamerules import GameSystemPerFrame +#from _engines._gamerules import BaseGameSystemPerFrame +#from _engines._gamerules import AutoGameSystemPerFrame from _engines._gamerules import GameRules +from _engines._gamerules import find_game_rules_property_offset +from _engines._gamerules import find_game_rules +from _engines._gamerules import find_game_rules_proxy_name # ============================================================================= # >> ALL DECLARATION # ============================================================================= __all__ = ( - 'AutoGameSystemPerFrame', - 'BaseGameSystemPerFrame', - 'GameSystem', - 'GameSystemPerFrame', +# 'AutoGameSystemPerFrame', +# 'BaseGameSystemPerFrame', +# 'GameSystem', +# 'GameSystemPerFrame', + 'GameRules', + 'find_game_rules_property_offset', 'find_game_rules', 'find_game_rules_proxy_name',) - - -# ============================================================================= -# >> FUNCTIONS -# ============================================================================= -def find_game_rules_proxy_name(): - """Find the entity name that proxies the game rules (e. g. - ``cs_gamerules``). - - :raise ValueError: - Raised if the game rules proxy name wasn't found. - :rtype: str - """ - for classname in factory_dictionary: - if 'gamerules' not in classname: - continue - - return classname - - raise ValueError('Unable to find game rules proxy name.') - -def find_game_rules(): - """Find the game rules instance. - - :raise ValueError: - Raised if the game rules instance wasn't found. - :rtype: GameRules - """ - proxy = BaseEntity.find_or_create(find_game_rules_proxy_name()) - cls = proxy.server_class - while cls: - for prop in cls.table: - if 'gamerules_data' not in prop.name: - continue - - return make_object( - GameRules, - prop.data_table_proxy_function(None, None, None, None, 0)) - - cls = cls.next - - raise ValueError('Unable to find game rules.') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e50f4afdd..b34cf3990 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -195,6 +195,7 @@ Set(SOURCEPYTHON_ENGINES_MODULE_HEADERS core/modules/engines/engines_server.h core/modules/engines/${SOURCE_ENGINE}/engines.h core/modules/engines/${SOURCE_ENGINE}/engines_wrap.h + core/modules/engines/engines_gamerules.h ) Set(SOURCEPYTHON_ENGINES_MODULE_SOURCES @@ -203,6 +204,7 @@ Set(SOURCEPYTHON_ENGINES_MODULE_SOURCES core/modules/engines/engines_server_wrap.cpp core/modules/engines/engines_sound_wrap.cpp core/modules/engines/engines_trace_wrap.cpp + core/modules/engines/engines_gamerules.cpp core/modules/engines/engines_gamerules_wrap.cpp ) diff --git a/src/core/modules/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp new file mode 100644 index 000000000..d48e436f7 --- /dev/null +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -0,0 +1,130 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 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. +//----------------------------------------------------------------------------- +// Source.Python +#include "engines_gamerules.h" +#include "modules/entities/entities_factories.h" +#include "modules/entities/entities_entity.h" +#include "modules/entities/entities_props.h" +#include "utilities/wrap_macros.h" + +// Boost.Python +#include "boost/python.hpp" +using namespace boost::python; + +// SDK +#include "strtools.h" + + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- +int find_game_rules_property_offset(const char* name) +{ + // TODO: I guess it's save to cache the server class... + + CBaseEntityWrapper* proxy = (CBaseEntityWrapper*) CBaseEntityWrapper::find_or_create(find_game_rules_proxy_name()); + + ServerClass* cls = proxy->GetServerClass(); + if (!cls) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Failed to retrieve the server class.") + + int offset; + offset = SendTableSharedExt::find_offset(cls->m_pTable, name); + if (offset == -1) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find property '%s'.", name) + + return offset; +} + +const char* find_game_rules_proxy_name() +{ + static const char* s_proxy_name = NULL; + int i = 0; + + if (s_proxy_name) + { + return s_proxy_name; + } + + CEntityFactoryDictionary* factory_dictionary = GetEntityFactoryDictionary(); + + while (factory_dictionary->m_Factories.IsValidIndex(i)) + { + const char* classname = factory_dictionary->m_Factories.GetElementName(i); + if (V_stristr(classname, "gamerules")) + { + // Cache the result + s_proxy_name = classname; + return classname; + } + + ++i; + } + + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find game rules proxy name."); + return NULL; +} + +CGameRulesWrapper* find_game_rules() +{ + // TODO: Can we cache the result? + + CBaseEntityWrapper* proxy = (CBaseEntityWrapper*) CBaseEntityWrapper::find_or_create(find_game_rules_proxy_name()); + + ServerClass* cls = proxy->GetServerClass(); + while (cls) + { + SendTable* table = cls->m_pTable; + for (int i=0; i < table->GetNumProps(); i++) + { + SendProp* prop = table->GetProp(i); + if (!V_stristr(prop->GetName(), "gamerules_data")) + { + continue; + } + + SendTableProxyFn proxy_func = prop->GetDataTableProxyFn(); + if (!proxy_func) + { + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Found game rules proxy entity, but proxy function is NULL."); + } + + // Pass the recipients. Some game's proxy functions require it for + // the game rules proxy. + CSendProxyRecipients recipients; + return (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); + } + + cls = cls->m_pNext; + } + + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Found game rules proxy entity, but proxy function is NULL."); + return NULL; +} diff --git a/src/core/modules/engines/engines_gamerules.h b/src/core/modules/engines/engines_gamerules.h new file mode 100644 index 000000000..2b8b46a80 --- /dev/null +++ b/src/core/modules/engines/engines_gamerules.h @@ -0,0 +1,101 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 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. +*/ + +#ifndef _ENGINES_GAMERULES_H +#define _ENGINES_GAMERULES_H + +//----------------------------------------------------------------------------- +// Includes. +//----------------------------------------------------------------------------- +// SDK +#include "strtools.h" + + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- +class CGameRulesWrapper; + +int find_game_rules_property_offset(const char* name); +const char* find_game_rules_proxy_name(); +CGameRulesWrapper* find_game_rules(); + + +//----------------------------------------------------------------------------- +// Classes. +//----------------------------------------------------------------------------- +class CGameRulesWrapper +{ +public: + + // Getter methods + template + T GetProperty(const char* name) + { + return GetPropertyByOffset(find_game_rules_property_offset(name)); + } + + template + T GetPropertyByOffset(int offset) + { + return *(T *) (((unsigned long) this) + offset); + } + + const char* GetPropertyStringArray(const char* name) + { + return GetPropertyStringArrayByOffset(find_game_rules_property_offset(name)); + } + + const char* GetPropertyStringArrayByOffset(int offset) + { + return (const char*) (((unsigned long) this) + offset); + } + + // Setter methods + template + void SetProperty(const char* name, T value) + { + SetPropertyByOffset(find_game_rules_property_offset(name), value); + } + + template + void SetPropertyByOffset(int offset, T value) + { + *(T *) (((unsigned long) this) + offset) = value; + } + + void SetPropertyStringArray(const char* name, const char* value) + { + SetPropertyStringArrayByOffset(find_game_rules_property_offset(name), value); + } + + void SetPropertyStringArrayByOffset(int offset, const char* value) + { + strcpy((char*) (((unsigned long) this) + offset), value); + } +}; + +#endif // _ENGINES_GAMERULES_H diff --git a/src/core/modules/engines/engines_gamerules_wrap.cpp b/src/core/modules/engines/engines_gamerules_wrap.cpp index e0a8b4fae..7a6d501b7 100644 --- a/src/core/modules/engines/engines_gamerules_wrap.cpp +++ b/src/core/modules/engines/engines_gamerules_wrap.cpp @@ -1,7 +1,7 @@ /** * ============================================================================= * Source Python -* Copyright (C) 2012-2015 Source Python Development Team. All rights reserved. +* Copyright (C) 2012-2020 Source Python Development Team. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -30,8 +30,14 @@ // Source.Python #include "export_main.h" #include "sp_main.h" +#include "engines_gamerules.h" // SDK +// CS:GO doesn't compile without the next two lines +#if defined(ENGINE_CSGO) + #include "baseanimating.h" + IUniformRandomStream* random; +#endif #include "game/shared/gamerules.h" @@ -50,6 +56,28 @@ void export_game_rules(scope); //--------------------------------------------------------------------------------- DECLARE_SP_SUBMODULE(_engines, _gamerules) { + def( + "find_game_rules_property_offset", + &find_game_rules_property_offset, + "Find the ooffset of a game rule property.\n\n" + ":rtype: int"); + def( + "find_game_rules_proxy_name", + &find_game_rules_proxy_name, + "Find the entity name that proxies the game rules (e. g. ``cs_gamerules``).\n\n" + ":raise ValueError:\n" + " Raised if the game rules proxy name wasn't found.\n" + ":rtype: str"); + + def( + "find_game_rules", + &find_game_rules, + "Find the game rules instance.\n\n" + ":raise ValueError:\n" + " Raised if the game rules instance wasn't found.\n" + ":rtype: GameRules\n", + reference_existing_object_policy()); + export_game_system(_gamerules); export_game_system_per_frame(_gamerules); export_base_game_system_per_frame(_gamerules); @@ -63,13 +91,13 @@ DECLARE_SP_SUBMODULE(_engines, _gamerules) //----------------------------------------------------------------------------- void export_game_system(scope _gamerules) { - class_ GameSystem("GameSystem", no_init); - - GameSystem.add_property( - "name", - &IGameSystem::Name); + //class_ GameSystem("GameSystem", no_init); + // + //GameSystem.add_property( + // "name", + // &IGameSystem::Name); - GameSystem ADD_MEM_TOOLS(IGameSystem); + //GameSystem ADD_MEM_TOOLS(IGameSystem); } @@ -78,9 +106,9 @@ void export_game_system(scope _gamerules) //----------------------------------------------------------------------------- void export_game_system_per_frame(scope _gamerules) { - class_, boost::noncopyable> GameSystemPerFrame("GameSystemPerFrame", no_init); + //class_, boost::noncopyable> GameSystemPerFrame("GameSystemPerFrame", no_init); - GameSystemPerFrame ADD_MEM_TOOLS(IGameSystemPerFrame); + //GameSystemPerFrame ADD_MEM_TOOLS(IGameSystemPerFrame); } @@ -89,9 +117,9 @@ void export_game_system_per_frame(scope _gamerules) //----------------------------------------------------------------------------- void export_base_game_system_per_frame(scope _gamerules) { - class_, boost::noncopyable> BaseGameSystemPerFrame("BaseGameSystemPerFrame", no_init); + //class_, boost::noncopyable> BaseGameSystemPerFrame("BaseGameSystemPerFrame", no_init); - BaseGameSystemPerFrame ADD_MEM_TOOLS(CBaseGameSystemPerFrame); + //BaseGameSystemPerFrame ADD_MEM_TOOLS(CBaseGameSystemPerFrame); } @@ -100,13 +128,13 @@ void export_base_game_system_per_frame(scope _gamerules) //----------------------------------------------------------------------------- void export_auto_game_system_per_frame(scope _gamerules) { - class_, boost::noncopyable> AutoGameSystemPerFrame("AutoGameSystemPerFrame", no_init); + //class_, boost::noncopyable> AutoGameSystemPerFrame("AutoGameSystemPerFrame", no_init); - AutoGameSystemPerFrame.add_property( - "next", - make_getter(&CAutoGameSystemPerFrame::m_pNext, reference_existing_object_policy())); + //AutoGameSystemPerFrame.add_property( + // "next", + // make_getter(&CAutoGameSystemPerFrame::m_pNext, reference_existing_object_policy())); - AutoGameSystemPerFrame ADD_MEM_TOOLS(CAutoGameSystemPerFrame); + //AutoGameSystemPerFrame ADD_MEM_TOOLS(CAutoGameSystemPerFrame); } @@ -115,21 +143,263 @@ void export_auto_game_system_per_frame(scope _gamerules) //----------------------------------------------------------------------------- void export_game_rules(scope _gamerules) { - class_, boost::noncopyable> GameRules("GameRules", no_init); + class_ GameRules("GameRules", no_init); + + //GameRules.add_property( + // "game_description", + // &CGameRulesWrapper::GetGameDescription); + + //GameRules.def( + // "should_collide", + // &CGameRulesWrapper::ShouldCollide); + + //GameRules.def( + // "get_tagged_convar_list", + // &CGameRulesWrapper::GetTaggedConVarList); + + // Generic property getters + GameRules.def("get_property_bool", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: bool" + ); + + GameRules.def("get_property_char", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: str" + ); + + GameRules.def("get_property_uchar", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_short", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_ushort", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_int", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_uint", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_long", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_ulong", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_long_long", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_ulong_long", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: int" + ); + + GameRules.def("get_property_float", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: float" + ); + + GameRules.def("get_property_double", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: float" + ); + + GameRules.def("get_property_string_pointer", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: str" + ); + + GameRules.def("get_property_string_array", + &CGameRulesWrapper::GetPropertyStringArray, + "Return the value of the given field name.\n\n" + ":rtype: str" + ); + + // Backward compatibility + GameRules.attr("get_property_string") = GameRules.attr("get_property_string_array"); + + GameRules.def("get_property_pointer", + &CGameRulesWrapper::GetProperty, + return_by_value_policy(), + "Return the value of the given field name.\n\n" + ":rtype: Pointer" + ); + + GameRules.def("get_property_vector", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Vector" + ); - GameRules.add_property( - "game_description", - &CGameRules::GetGameDescription); + GameRules.def("get_property_color", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Color" + ); - GameRules.def( - "should_collide", - &CGameRules::ShouldCollide); + GameRules.def("get_property_interval", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Interval" + ); - GameRules.def( - "get_tagged_convar_list", - &CGameRules::GetTaggedConVarList); + GameRules.def("get_property_quaternion", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Quaternion" + ); - GameRules ADD_MEM_TOOLS(CGameRules); + GameRules.def("get_property_edict", + &CGameRulesWrapper::GetProperty, + return_by_value_policy(), + "Return the value of the given field name.\n\n" + ":rtype: Edict" + ); + + // Generic property setters + GameRules.def("set_property_bool", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_char", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_uchar", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_short", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_ushort", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_int", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_uint", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_long", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_ulong", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_long_long", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_ulong_long", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_float", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_double", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_string_pointer", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_string_array", + &CGameRulesWrapper::SetPropertyStringArray, + "Set the value of the given field name." + ); + + // Backward compatibility + GameRules.attr("set_property_string") = GameRules.attr("set_property_string_array"); + + GameRules.def("set_property_pointer", + &CGameRulesWrapper::SetProperty, + return_by_value_policy(), + "Set the value of the given field name." + ); + + GameRules.def("set_property_vector", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_color", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_interval", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_quaternion", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules.def("set_property_edict", + &CGameRulesWrapper::SetProperty, + "Set the value of the given field name." + ); + + GameRules ADD_MEM_TOOLS_WRAPPER(CGameRulesWrapper, CGameRules); BEGIN_CLASS_INFO(CGameRules) FUNCTION_INFO(DeathNotice) diff --git a/src/core/modules/entities/entities_props_wrap.cpp b/src/core/modules/entities/entities_props_wrap.cpp index 3f0fea5d1..f1779182e 100644 --- a/src/core/modules/entities/entities_props_wrap.cpp +++ b/src/core/modules/entities/entities_props_wrap.cpp @@ -295,6 +295,8 @@ void export_send_proxy_recipients(scope _props) "clear_all_recipients", &CSendProxyRecipients::ClearAllRecipients); + /* + // These two are not implemented in the header in some games (e. g. CS:GO). SendProxyRecipients.def( "set_recipient", &CSendProxyRecipients::SetRecipient); @@ -302,6 +304,7 @@ void export_send_proxy_recipients(scope _props) SendProxyRecipients.def( "set_only", &CSendProxyRecipients::SetOnly); + */ // TODO: m_Bits From 0f13f644b7e2c58ac4985634a82c54654bf61e5f Mon Sep 17 00:00:00 2001 From: Ayuto Date: Fri, 11 Dec 2020 23:00:50 +0100 Subject: [PATCH 3/9] Moved stringtables stuff to the appropriate files Fixed StringTable.changed_since_tick() calling the wrong C++ function --- src/CMakeLists.txt | 2 + .../modules/stringtables/stringtables.cpp | 134 ++++++++++++++++ src/core/modules/stringtables/stringtables.h | 64 ++++++++ .../stringtables/stringtables_wrap.cpp | 150 ++---------------- 4 files changed, 212 insertions(+), 138 deletions(-) create mode 100644 src/core/modules/stringtables/stringtables.cpp create mode 100644 src/core/modules/stringtables/stringtables.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b34cf3990..9bb21297a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -438,9 +438,11 @@ Set(SOURCEPYTHON_STEAM_MODULE_SOURCES # StringTables module. # ------------------------------------------------------------------ Set(SOURCEPYTHON_STRINGTABLES_MODULE_HEADERS + core/modules/stringtables/stringtables.h ) Set(SOURCEPYTHON_STRINGTABLES_MODULE_SOURCES + core/modules/stringtables/stringtables.cpp core/modules/stringtables/stringtables_wrap.cpp ) diff --git a/src/core/modules/stringtables/stringtables.cpp b/src/core/modules/stringtables/stringtables.cpp new file mode 100644 index 000000000..fa5b36381 --- /dev/null +++ b/src/core/modules/stringtables/stringtables.cpp @@ -0,0 +1,134 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2015 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. +//--------------------------------------------------------------------------------- +#include "stringtables.h" + +//--------------------------------------------------------------------------------- +// External variables to use. +//--------------------------------------------------------------------------------- +extern IVEngineServer* engine; + + +//----------------------------------------------------------------------------- +// INetworkStringTableExt +//----------------------------------------------------------------------------- +bool INetworkStringTableExt::__contains__( INetworkStringTable *pTable, const char *string ) +{ + return pTable->FindStringIndex(string) != INVALID_STRING_INDEX; +} + +const char* INetworkStringTableExt::GetString(INetworkStringTable& table, int index) +{ + if ((index < 0) || (index >= table.GetNumStrings())) + BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range.") + + return table.GetString(index); +} + +int INetworkStringTableExt::AddString( INetworkStringTable *pTable, const char *string, const char *user_data, int length, bool is_server, bool auto_unlock ) +{ + int index = INVALID_STRING_INDEX; + bool locked = false; + if (auto_unlock) + { + locked = engine->LockNetworkStringTables(false); + } + if (user_data && pTable->FindStringIndex(string) == INVALID_STRING_INDEX && length == -1) + { + length = strlen(user_data) + 1; + } + index = pTable->AddString(is_server, string, length, (const void *)user_data); + if (locked && auto_unlock) + { + engine->LockNetworkStringTables(locked); + } + return index; +} + +void INetworkStringTableExt::SetStringIndexUserData( INetworkStringTable *pTable, int string_index, const char *user_data, int length ) +{ + if (length == -1) + { + length = strlen(user_data) + 1; + } + pTable->SetStringUserData(string_index, length, user_data); +} + +void INetworkStringTableExt::SetStringUserData( INetworkStringTable *pTable, const char *string, const char *user_data, int length ) +{ + int string_index = pTable->FindStringIndex(string); + if (string_index == INVALID_STRING_INDEX) + { + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") + } + SetStringIndexUserData(pTable, string_index, user_data, length); +} + +const char* INetworkStringTableExt::GetStringIndexUserData( INetworkStringTable *pTable, int string_index ) +{ + return (const char *)pTable->GetStringUserData(string_index, NULL); +} + +const char* INetworkStringTableExt::GetStringUserData( INetworkStringTable *pTable, const char *string ) +{ + int index = pTable->FindStringIndex(string); + if (index == INVALID_STRING_INDEX) + { + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") + } + return GetStringIndexUserData(pTable, index); +} + +int INetworkStringTableExt::GetStringIndexUserDataLength( INetworkStringTable *pTable, int string_index ) +{ + int length = 0; + const void * user_data = pTable->GetStringUserData(string_index, &length); + return length; +} + +int INetworkStringTableExt::GetStringUserDataLength( INetworkStringTable *pTable, const char *string ) +{ + int index = pTable->FindStringIndex(string); + if (index == INVALID_STRING_INDEX) + { + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") + } + return GetStringIndexUserDataLength(pTable, index); +} + +//--------------------------------------------------------------------------------- +// INetworkStringTableContainerExt +//--------------------------------------------------------------------------------- +INetworkStringTable* INetworkStringTableContainerExt::GetTable(INetworkStringTableContainer& table_container, TABLEID table_id) +{ + if ((table_id < 0) || (table_id >= table_container.GetNumTables())) + BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range.") + + return table_container.GetTable(table_id); +} \ No newline at end of file diff --git a/src/core/modules/stringtables/stringtables.h b/src/core/modules/stringtables/stringtables.h new file mode 100644 index 000000000..ca83c9cae --- /dev/null +++ b/src/core/modules/stringtables/stringtables.h @@ -0,0 +1,64 @@ +/** +* ============================================================================= +* Source Python +* Copyright (C) 2012-2020 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. +*/ + +#ifndef _STRINGTABLES_H +#define _STRINGTABLES_H + +//----------------------------------------------------------------------------- +// Includes. +//----------------------------------------------------------------------------- +#include "utilities/wrap_macros.h" +#include "networkstringtabledefs.h" +#include "eiface.h" + + +//----------------------------------------------------------------------------- +// INetworkStringTableExt +//----------------------------------------------------------------------------- +class INetworkStringTableExt +{ +public: + static const char* GetString(INetworkStringTable& table, int index); + static bool __contains__( INetworkStringTable *pTable, const char *string ); + static int AddString( INetworkStringTable *pTable, const char *string, const char *user_data, int length, bool is_server, bool auto_unlock ); + static void SetStringIndexUserData( INetworkStringTable *pTable, int string_index, const char *user_data, int length ); + static void SetStringUserData( INetworkStringTable *pTable, const char *string, const char *user_data, int length ); + static const char *GetStringIndexUserData( INetworkStringTable *pTable, int string_index ); + static const char *GetStringUserData( INetworkStringTable *pTable, const char *string ); + static int GetStringIndexUserDataLength( INetworkStringTable *pTable, int string_index ); + static int GetStringUserDataLength( INetworkStringTable *pTable, const char *string ); +}; + +//--------------------------------------------------------------------------------- +// INetworkStringTableContainerExt +//--------------------------------------------------------------------------------- +class INetworkStringTableContainerExt +{ +public: + static INetworkStringTable* GetTable(INetworkStringTableContainer& table_container, TABLEID table_id); +}; + +#endif // _STRINGTABLES_H diff --git a/src/core/modules/stringtables/stringtables_wrap.cpp b/src/core/modules/stringtables/stringtables_wrap.cpp index b6883724f..b8e621cbd 100644 --- a/src/core/modules/stringtables/stringtables_wrap.cpp +++ b/src/core/modules/stringtables/stringtables_wrap.cpp @@ -29,16 +29,13 @@ //--------------------------------------------------------------------------------- #include "export_main.h" #include "modules/memory/memory_tools.h" - -#include "utilities/wrap_macros.h" -#include "networkstringtabledefs.h" -#include "eiface.h" +#include "stringtables.h" //--------------------------------------------------------------------------------- // External variables to use. //--------------------------------------------------------------------------------- extern INetworkStringTableContainer *networkstringtable; -extern IVEngineServer* engine; + //--------------------------------------------------------------------------------- // Forward declarations. @@ -46,6 +43,7 @@ extern IVEngineServer* engine; void export_stringtable(scope); void export_stringtable_container(scope); + //--------------------------------------------------------------------------------- // Declares the stringtables_c module. //--------------------------------------------------------------------------------- @@ -58,121 +56,9 @@ DECLARE_SP_MODULE(_stringtables) _stringtables.attr("INVALID_STRING_INDEX") = INVALID_STRING_INDEX; } -//--------------------------------------------------------------------------------- -// Add a string to the specified table. -//--------------------------------------------------------------------------------- -int AddString( INetworkStringTable *pTable, const char *string, const char *user_data, int length, bool is_server, bool auto_unlock ) -{ - int index = INVALID_STRING_INDEX; - bool locked = false; - if (auto_unlock) - { - locked = engine->LockNetworkStringTables(false); - } - if (user_data && pTable->FindStringIndex(string) == INVALID_STRING_INDEX && length == -1) - { - length = strlen(user_data) + 1; - } - index = pTable->AddString(is_server, string, length, (const void *)user_data); - if (locked && auto_unlock) - { - engine->LockNetworkStringTables(locked); - } - return index; -} - -//--------------------------------------------------------------------------------- -// Sets the user data of the given string index. -//--------------------------------------------------------------------------------- -void SetStringIndexUserData( INetworkStringTable *pTable, int string_index, const char *user_data, int length ) -{ - if (length == -1) - { - length = strlen(user_data) + 1; - } - pTable->SetStringUserData(string_index, length, user_data); -} - -//--------------------------------------------------------------------------------- -// Sets the user data of the given string. -//--------------------------------------------------------------------------------- -void SetStringUserData( INetworkStringTable *pTable, const char *string, const char *user_data, int length ) -{ - int string_index = pTable->FindStringIndex(string); - if (string_index == INVALID_STRING_INDEX) - { - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") - } - SetStringIndexUserData(pTable, string_index, user_data, length); -} - -//--------------------------------------------------------------------------------- -// Returns the user data of the given string index. -//--------------------------------------------------------------------------------- -const char *GetStringIndexUserData( INetworkStringTable *pTable, int string_index ) -{ - return (const char *)pTable->GetStringUserData(string_index, NULL); -} - -//--------------------------------------------------------------------------------- -// Returns the user data of the given string. -//--------------------------------------------------------------------------------- -const char *GetStringUserData( INetworkStringTable *pTable, const char *string ) -{ - int index = pTable->FindStringIndex(string); - if (index == INVALID_STRING_INDEX) - { - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") - } - return GetStringIndexUserData(pTable, index); -} - -//--------------------------------------------------------------------------------- -// Returns the length of the user data of the given string index. -//--------------------------------------------------------------------------------- -int GetStringIndexUserDataLength( INetworkStringTable *pTable, int string_index ) -{ - int length = 0; - const void * user_data = pTable->GetStringUserData(string_index, &length); - return length; -} - -//--------------------------------------------------------------------------------- -// Returns the user data of the given string. -//--------------------------------------------------------------------------------- -int GetStringUserDataLength( INetworkStringTable *pTable, const char *string ) -{ - int index = pTable->FindStringIndex(string); - if (index == INVALID_STRING_INDEX) - { - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Given string not found.") - } - return GetStringIndexUserDataLength(pTable, index); -} - -//--------------------------------------------------------------------------------- -// Returns whether or not the given string is in the table -//--------------------------------------------------------------------------------- -bool __contains__( INetworkStringTable *pTable, const char *string ) -{ - return pTable->FindStringIndex(string) != INVALID_STRING_INDEX; -} - //--------------------------------------------------------------------------------- // Exposes INetworkStringTable. //--------------------------------------------------------------------------------- -class INetworkStringTableExt -{ -public: - static const char* GetString(INetworkStringTable& table, int index) - { - if ((index < 0) || (index >= table.GetNumStrings())) - BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range.") - - return table.GetString(index); - } -}; - void export_stringtable(scope _stringtables) { class_("StringTable", no_init) @@ -193,7 +79,7 @@ void export_stringtable(scope _stringtables) ) .def("__contains__", - &__contains__, + &INetworkStringTableExt::__contains__, "Returns whether or not the given string is contained in the table." ) @@ -214,13 +100,13 @@ void export_stringtable(scope _stringtables) ) .def("changed_since_tick", - &INetworkStringTable::SetTick, + &INetworkStringTable::ChangedSinceTick, "Returns True if the table has been modified since the given tick, False otherwise.", ("tick") ) .def("add_string", - &AddString, + &INetworkStringTableExt::AddString, "Adds the given string to the table.", ("string", arg("user_data")=object(), arg("length")=-1, arg("is_server")=true, arg("auto_unlock")=true) ) @@ -232,25 +118,25 @@ void export_stringtable(scope _stringtables) ) .def("set_user_data", - &SetStringIndexUserData, + &INetworkStringTableExt::SetStringIndexUserData, "Sets the user data of the given string index.", ("string_index", "user_data", arg("length")=-1) ) .def("set_user_data", - &SetStringUserData, + &INetworkStringTableExt::SetStringUserData, "Sets the user data of the given string.", ("string", "user_data", arg("length")=-1) ) .def("get_user_data", - &GetStringIndexUserData, + &INetworkStringTableExt::GetStringIndexUserData, "Returns the user data of the given string index.", ("string_index") ) .def("get_user_data", - &GetStringUserData, + &INetworkStringTableExt::GetStringUserData, "Returns the user data of the given string.", ("string") ) @@ -262,13 +148,13 @@ void export_stringtable(scope _stringtables) ) .def("get_user_data_length", - &GetStringIndexUserDataLength, + &INetworkStringTableExt::GetStringIndexUserDataLength, "Returns the length of the user data of the given string index.", ("string_index") ) .def("get_user_data_length", - &GetStringUserDataLength, + &INetworkStringTableExt::GetStringUserDataLength, "Returns the length of the user data of the given string.", ("string") ) @@ -280,18 +166,6 @@ void export_stringtable(scope _stringtables) //--------------------------------------------------------------------------------- // Exposes INetworkStringTableContainer. //--------------------------------------------------------------------------------- -class INetworkStringTableContainerExt -{ -public: - static INetworkStringTable* GetTable(INetworkStringTableContainer& table_container, TABLEID table_id) - { - if ((table_id < 0) || (table_id >= table_container.GetNumTables())) - BOOST_RAISE_EXCEPTION(PyExc_IndexError, "Index out of range.") - - return table_container.GetTable(table_id); - } -}; - void export_stringtable_container(scope _stringtables) { class_("_StringTables", no_init) From 7777708fff7e8edaa627ab9ba4ee1f827a4338c5 Mon Sep 17 00:00:00 2001 From: Ayuto Date: Fri, 11 Dec 2020 23:01:31 +0100 Subject: [PATCH 4/9] Added static method ServerClass.find_server_class() --- src/core/modules/entities/entities_props.cpp | 31 +++++++++++++++++++ src/core/modules/entities/entities_props.h | 11 +++++++ .../modules/entities/entities_props_wrap.cpp | 7 +++++ 3 files changed, 49 insertions(+) diff --git a/src/core/modules/entities/entities_props.cpp b/src/core/modules/entities/entities_props.cpp index 32bbd49c4..34b65f22f 100644 --- a/src/core/modules/entities/entities_props.cpp +++ b/src/core/modules/entities/entities_props.cpp @@ -35,6 +35,16 @@ #include "entities_props.h" #include ENGINE_INCLUDE_PATH(entities_props.h) +// SDK +#include "eiface.h" +#include "public/server_class.h" + + +//----------------------------------------------------------------------------- +// External variables. +//----------------------------------------------------------------------------- +extern IServerGameDLL* servergamedll; + // ============================================================================ // >> TYPEDEFS @@ -100,6 +110,27 @@ void AddSendTable(SendTable* pTable, OffsetsMap& offsets, int offset=0, const ch } +// ============================================================================ +// >> ServerClassExt +// ============================================================================ +ServerClass* ServerClassExt::find_server_class(const char* name) +{ + ServerClass* current = servergamedll->GetAllServerClasses(); + while (current) + { + if (V_strcmp(current->GetName(), name) == 0) + { + return current; + } + + current = current->m_pNext; + } + + BOOST_RAISE_EXCEPTION(PyExc_NameError, "Unable to find server class %s.", name); + return NULL; +} + + // ============================================================================ // >> SendTableSharedExt // ============================================================================ diff --git a/src/core/modules/entities/entities_props.h b/src/core/modules/entities/entities_props.h index ab30b445e..f9a983156 100644 --- a/src/core/modules/entities/entities_props.h +++ b/src/core/modules/entities/entities_props.h @@ -49,6 +49,17 @@ BOOST_FUNCTION_TYPEDEF(int (const void *pStruct, int objectID), BoostArrayLength // Forward declarations //----------------------------------------------------------------------------- class CPointer; +class ServerClass; + + +//----------------------------------------------------------------------------- +// ServerClass extension class. +//----------------------------------------------------------------------------- +class ServerClassExt +{ +public: + static ServerClass* find_server_class(const char* name); +}; //----------------------------------------------------------------------------- diff --git a/src/core/modules/entities/entities_props_wrap.cpp b/src/core/modules/entities/entities_props_wrap.cpp index f1779182e..39a7b8484 100644 --- a/src/core/modules/entities/entities_props_wrap.cpp +++ b/src/core/modules/entities/entities_props_wrap.cpp @@ -265,6 +265,13 @@ void export_send_prop_variant(scope _props) void export_server_class(scope _props) { class_ ServerClass_("ServerClass", no_init); + + ServerClass_.def( + "find_server_class", + &ServerClassExt::find_server_class, + "Lookup a ServerClass by its name\n\n" + ":rtype: str", + reference_existing_object_policy()).staticmethod("find_server_class"); // Properties... ServerClass_.def_readonly("table", &ServerClass::m_pTable); From 4c0b66720a9b21dbd045bd7331275485a8b5b440 Mon Sep 17 00:00:00 2001 From: Ayuto Date: Fri, 11 Dec 2020 23:05:44 +0100 Subject: [PATCH 5/9] Added back those two --- src/core/modules/entities/entities_props_wrap.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/modules/entities/entities_props_wrap.cpp b/src/core/modules/entities/entities_props_wrap.cpp index 39a7b8484..1ec5e6352 100644 --- a/src/core/modules/entities/entities_props_wrap.cpp +++ b/src/core/modules/entities/entities_props_wrap.cpp @@ -302,8 +302,6 @@ void export_send_proxy_recipients(scope _props) "clear_all_recipients", &CSendProxyRecipients::ClearAllRecipients); - /* - // These two are not implemented in the header in some games (e. g. CS:GO). SendProxyRecipients.def( "set_recipient", &CSendProxyRecipients::SetRecipient); @@ -311,7 +309,6 @@ void export_send_proxy_recipients(scope _props) SendProxyRecipients.def( "set_only", &CSendProxyRecipients::SetOnly); - */ // TODO: m_Bits From fceb3a668a4f4e700699136c78487ca74a141286 Mon Sep 17 00:00:00 2001 From: Ayuto Date: Fri, 11 Dec 2020 23:09:22 +0100 Subject: [PATCH 6/9] Reimplemented gamerules functions using string tables --- .../modules/engines/engines_gamerules.cpp | 86 +++++++------------ 1 file changed, 30 insertions(+), 56 deletions(-) diff --git a/src/core/modules/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp index d48e436f7..888be6b7e 100644 --- a/src/core/modules/engines/engines_gamerules.cpp +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -38,8 +38,11 @@ #include "boost/python.hpp" using namespace boost::python; -// SDK -#include "strtools.h" + +//--------------------------------------------------------------------------------- +// External variables to use. +//--------------------------------------------------------------------------------- +extern INetworkStringTableContainer *networkstringtable; //----------------------------------------------------------------------------- @@ -47,16 +50,9 @@ using namespace boost::python; //----------------------------------------------------------------------------- int find_game_rules_property_offset(const char* name) { - // TODO: I guess it's save to cache the server class... - - CBaseEntityWrapper* proxy = (CBaseEntityWrapper*) CBaseEntityWrapper::find_or_create(find_game_rules_proxy_name()); - - ServerClass* cls = proxy->GetServerClass(); - if (!cls) - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Failed to retrieve the server class.") + ServerClass* cls = ServerClassExt::find_server_class(find_game_rules_proxy_name()); + int offset = SendTableSharedExt::find_offset(cls->m_pTable, name); - int offset; - offset = SendTableSharedExt::find_offset(cls->m_pTable, name); if (offset == -1) BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find property '%s'.", name) @@ -66,65 +62,43 @@ int find_game_rules_property_offset(const char* name) const char* find_game_rules_proxy_name() { static const char* s_proxy_name = NULL; - int i = 0; - if (s_proxy_name) - { - return s_proxy_name; - } - - CEntityFactoryDictionary* factory_dictionary = GetEntityFactoryDictionary(); - - while (factory_dictionary->m_Factories.IsValidIndex(i)) - { - const char* classname = factory_dictionary->m_Factories.GetElementName(i); - if (V_stristr(classname, "gamerules")) - { - // Cache the result - s_proxy_name = classname; - return classname; - } - ++i; - } - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find game rules proxy name."); return NULL; } -CGameRulesWrapper* find_game_rules() +SendTableProxyFn find_game_rules_proxy_function() { - // TODO: Can we cache the result? + SendTableProxyFn s_proxy_func = NULL; + if (s_proxy_func) + return s_proxy_func; - CBaseEntityWrapper* proxy = (CBaseEntityWrapper*) CBaseEntityWrapper::find_or_create(find_game_rules_proxy_name()); + ServerClass* cls = ServerClassExt::find_server_class(find_game_rules_proxy_name()); + SendTable* table = cls->m_pTable; - ServerClass* cls = proxy->GetServerClass(); - while (cls) + for (int i=0; i < table->GetNumProps(); i++) { - SendTable* table = cls->m_pTable; - for (int i=0; i < table->GetNumProps(); i++) + SendProp* prop = table->GetProp(i); + if (!V_stristr(prop->GetName(), "gamerules_data")) { - SendProp* prop = table->GetProp(i); - if (!V_stristr(prop->GetName(), "gamerules_data")) - { - continue; - } - - SendTableProxyFn proxy_func = prop->GetDataTableProxyFn(); - if (!proxy_func) - { - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Found game rules proxy entity, but proxy function is NULL."); - } - - // Pass the recipients. Some game's proxy functions require it for - // the game rules proxy. - CSendProxyRecipients recipients; - return (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); + continue; } - cls = cls->m_pNext; + SendTableProxyFn s_proxy_func = prop->GetDataTableProxyFn(); + if (!s_proxy_func) + { + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules proxy function is NULL."); + } } - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Found game rules proxy entity, but proxy function is NULL."); return NULL; } + +CGameRulesWrapper* find_game_rules() +{ + SendTableProxyFn proxy_func = find_game_rules_proxy_function(); + static CSendProxyRecipients recipients; + + return (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); +} From c48d7dc8794a59659fc2eebd3c1a8c72645e4f9b Mon Sep 17 00:00:00 2001 From: Ayuto Date: Sat, 12 Dec 2020 00:33:01 +0100 Subject: [PATCH 7/9] Cleanup, sanity checks and typos --- .../source-python/engines/gamerules.py | 19 ----- .../modules/engines/engines_gamerules.cpp | 41 +++++++--- .../engines/engines_gamerules_wrap.cpp | 82 +------------------ 3 files changed, 30 insertions(+), 112 deletions(-) diff --git a/addons/source-python/packages/source-python/engines/gamerules.py b/addons/source-python/packages/source-python/engines/gamerules.py index 98400102a..409890d78 100644 --- a/addons/source-python/packages/source-python/engines/gamerules.py +++ b/addons/source-python/packages/source-python/engines/gamerules.py @@ -2,26 +2,11 @@ """Provides access to the gamerules instance.""" -# ============================================================================= -# >> IMPORTS -# ============================================================================= -# Source.Python Imports -# Memory -from memory import make_object -# Entities -from entities.entity import BaseEntity -from entities.factories import factory_dictionary - - # ============================================================================= # >> FORWARD IMPORTS # ============================================================================= # Source.Python Imports # Engines -#from _engines._gamerules import GameSystem -#from _engines._gamerules import GameSystemPerFrame -#from _engines._gamerules import BaseGameSystemPerFrame -#from _engines._gamerules import AutoGameSystemPerFrame from _engines._gamerules import GameRules from _engines._gamerules import find_game_rules_property_offset from _engines._gamerules import find_game_rules @@ -32,10 +17,6 @@ # >> ALL DECLARATION # ============================================================================= __all__ = ( -# 'AutoGameSystemPerFrame', -# 'BaseGameSystemPerFrame', -# 'GameSystem', -# 'GameSystemPerFrame', 'GameRules', 'find_game_rules_property_offset', 'find_game_rules', diff --git a/src/core/modules/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp index 888be6b7e..379466205 100644 --- a/src/core/modules/engines/engines_gamerules.cpp +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -29,15 +29,17 @@ //----------------------------------------------------------------------------- // Source.Python #include "engines_gamerules.h" -#include "modules/entities/entities_factories.h" -#include "modules/entities/entities_entity.h" #include "modules/entities/entities_props.h" +#include "modules/stringtables/stringtables.h" #include "utilities/wrap_macros.h" // Boost.Python #include "boost/python.hpp" using namespace boost::python; +// SDK +#include "server_class.h" + //--------------------------------------------------------------------------------- // External variables to use. @@ -61,17 +63,28 @@ int find_game_rules_property_offset(const char* name) const char* find_game_rules_proxy_name() { - static const char* s_proxy_name = NULL; + static std::string s_proxy_name; + if (!s_proxy_name.empty()) + // Use cache + return s_proxy_name.c_str(); + INetworkStringTable* table = networkstringtable->FindTable("GameRulesCreation"); + if (!table) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find string table 'GameRulesCreation'.") + s_proxy_name = INetworkStringTableExt::GetStringUserData(table, "classname"); + if (s_proxy_name.empty()) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "'classname' of string table 'GameRulesCreation' is NULL.") - return NULL; + s_proxy_name += "Proxy"; + return s_proxy_name.c_str(); } SendTableProxyFn find_game_rules_proxy_function() { SendTableProxyFn s_proxy_func = NULL; if (s_proxy_func) + // Use cache return s_proxy_func; ServerClass* cls = ServerClassExt::find_server_class(find_game_rules_proxy_name()); @@ -81,24 +94,26 @@ SendTableProxyFn find_game_rules_proxy_function() { SendProp* prop = table->GetProp(i); if (!V_stristr(prop->GetName(), "gamerules_data")) - { continue; - } - SendTableProxyFn s_proxy_func = prop->GetDataTableProxyFn(); - if (!s_proxy_func) - { - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules proxy function is NULL."); - } + s_proxy_func = prop->GetDataTableProxyFn(); + break; } - return NULL; + if (!s_proxy_func) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules proxy function is NULL."); + + return s_proxy_func; } CGameRulesWrapper* find_game_rules() { SendTableProxyFn proxy_func = find_game_rules_proxy_function(); static CSendProxyRecipients recipients; + + CGameRulesWrapper* game_rules = (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); + if (!game_rules) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules pointer is NULL."); - return (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); + return game_rules; } diff --git a/src/core/modules/engines/engines_gamerules_wrap.cpp b/src/core/modules/engines/engines_gamerules_wrap.cpp index 7a6d501b7..8c68af30f 100644 --- a/src/core/modules/engines/engines_gamerules_wrap.cpp +++ b/src/core/modules/engines/engines_gamerules_wrap.cpp @@ -33,21 +33,11 @@ #include "engines_gamerules.h" // SDK -// CS:GO doesn't compile without the next two lines -#if defined(ENGINE_CSGO) - #include "baseanimating.h" - IUniformRandomStream* random; -#endif #include "game/shared/gamerules.h" - //--------------------------------------------------------------------------------- // Forward declarations. //--------------------------------------------------------------------------------- -void export_game_system(scope); -void export_game_system_per_frame(scope); -void export_base_game_system_per_frame(scope); -void export_auto_game_system_per_frame(scope); void export_game_rules(scope); @@ -59,12 +49,12 @@ DECLARE_SP_SUBMODULE(_engines, _gamerules) def( "find_game_rules_property_offset", &find_game_rules_property_offset, - "Find the ooffset of a game rule property.\n\n" + "Find the offset of a game rules property.\n\n" ":rtype: int"); def( "find_game_rules_proxy_name", &find_game_rules_proxy_name, - "Find the entity name that proxies the game rules (e. g. ``cs_gamerules``).\n\n" + "Find the server class of the game rules proxy entity (e. g. ``CCSGameRulesProxy``).\n\n" ":raise ValueError:\n" " Raised if the game rules proxy name wasn't found.\n" ":rtype: str"); @@ -78,66 +68,10 @@ DECLARE_SP_SUBMODULE(_engines, _gamerules) ":rtype: GameRules\n", reference_existing_object_policy()); - export_game_system(_gamerules); - export_game_system_per_frame(_gamerules); - export_base_game_system_per_frame(_gamerules); - export_auto_game_system_per_frame(_gamerules); export_game_rules(_gamerules); } -//----------------------------------------------------------------------------- -// Expose GameSystem. -//----------------------------------------------------------------------------- -void export_game_system(scope _gamerules) -{ - //class_ GameSystem("GameSystem", no_init); - // - //GameSystem.add_property( - // "name", - // &IGameSystem::Name); - - //GameSystem ADD_MEM_TOOLS(IGameSystem); -} - - -//----------------------------------------------------------------------------- -// Expose GameSystemPerFrame. -//----------------------------------------------------------------------------- -void export_game_system_per_frame(scope _gamerules) -{ - //class_, boost::noncopyable> GameSystemPerFrame("GameSystemPerFrame", no_init); - - //GameSystemPerFrame ADD_MEM_TOOLS(IGameSystemPerFrame); -} - - -//----------------------------------------------------------------------------- -// Expose BaseGameSystemPerFrame. -//----------------------------------------------------------------------------- -void export_base_game_system_per_frame(scope _gamerules) -{ - //class_, boost::noncopyable> BaseGameSystemPerFrame("BaseGameSystemPerFrame", no_init); - - //BaseGameSystemPerFrame ADD_MEM_TOOLS(CBaseGameSystemPerFrame); -} - - -//----------------------------------------------------------------------------- -// Expose AutoGameSystemPerFrame. -//----------------------------------------------------------------------------- -void export_auto_game_system_per_frame(scope _gamerules) -{ - //class_, boost::noncopyable> AutoGameSystemPerFrame("AutoGameSystemPerFrame", no_init); - - //AutoGameSystemPerFrame.add_property( - // "next", - // make_getter(&CAutoGameSystemPerFrame::m_pNext, reference_existing_object_policy())); - - //AutoGameSystemPerFrame ADD_MEM_TOOLS(CAutoGameSystemPerFrame); -} - - //----------------------------------------------------------------------------- // Expose GameRules. //----------------------------------------------------------------------------- @@ -145,18 +79,6 @@ void export_game_rules(scope _gamerules) { class_ GameRules("GameRules", no_init); - //GameRules.add_property( - // "game_description", - // &CGameRulesWrapper::GetGameDescription); - - //GameRules.def( - // "should_collide", - // &CGameRulesWrapper::ShouldCollide); - - //GameRules.def( - // "get_tagged_convar_list", - // &CGameRulesWrapper::GetTaggedConVarList); - // Generic property getters GameRules.def("get_property_bool", &CGameRulesWrapper::GetProperty, From 7a72777535e11e002989a352b6e298173057f86d Mon Sep 17 00:00:00 2001 From: Ayuto Date: Sat, 12 Dec 2020 00:34:40 +0100 Subject: [PATCH 8/9] Fixed spacing --- src/core/modules/engines/engines_gamerules.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/modules/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp index 379466205..04ade5a6f 100644 --- a/src/core/modules/engines/engines_gamerules.cpp +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -113,7 +113,7 @@ CGameRulesWrapper* find_game_rules() CGameRulesWrapper* game_rules = (CGameRulesWrapper*) proxy_func(NULL, NULL, NULL, &recipients, 0); if (!game_rules) - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules pointer is NULL."); + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Game rules pointer is NULL."); return game_rules; } From 4a466cc3b49fe7ef9c3436cf0fb37900096b3418 Mon Sep 17 00:00:00 2001 From: Ayuto Date: Tue, 15 Dec 2020 00:16:37 +0100 Subject: [PATCH 9/9] Cache SendTable --- src/core/modules/engines/engines_gamerules.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/modules/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp index 04ade5a6f..1dcda625b 100644 --- a/src/core/modules/engines/engines_gamerules.cpp +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -52,8 +52,14 @@ extern INetworkStringTableContainer *networkstringtable; //----------------------------------------------------------------------------- int find_game_rules_property_offset(const char* name) { - ServerClass* cls = ServerClassExt::find_server_class(find_game_rules_proxy_name()); - int offset = SendTableSharedExt::find_offset(cls->m_pTable, name); + static SendTable* s_table = NULL; + if (!s_table) + { + ServerClass* cls = ServerClassExt::find_server_class(find_game_rules_proxy_name()); + s_table = cls->m_pTable; + } + + int offset = SendTableSharedExt::find_offset(s_table, name); if (offset == -1) BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Unable to find property '%s'.", name)