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..409890d78 --- /dev/null +++ b/addons/source-python/packages/source-python/engines/gamerules.py @@ -0,0 +1,23 @@ +# ../engines/gamerules.py + +"""Provides access to the gamerules instance.""" + +# ============================================================================= +# >> FORWARD IMPORTS +# ============================================================================= +# Source.Python Imports +# Engines +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__ = ( + 'GameRules', + 'find_game_rules_property_offset', + 'find_game_rules', + 'find_game_rules_proxy_name',) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6df2fd77..9bb21297a 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,8 @@ 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 ) # ------------------------------------------------------------------ @@ -435,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/engines/engines_gamerules.cpp b/src/core/modules/engines/engines_gamerules.cpp new file mode 100644 index 000000000..1dcda625b --- /dev/null +++ b/src/core/modules/engines/engines_gamerules.cpp @@ -0,0 +1,125 @@ +/** +* ============================================================================= +* 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_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. +//--------------------------------------------------------------------------------- +extern INetworkStringTableContainer *networkstringtable; + + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- +int find_game_rules_property_offset(const char* 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) + + return offset; +} + +const char* find_game_rules_proxy_name() +{ + 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.") + + 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()); + 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; + + s_proxy_func = prop->GetDataTableProxyFn(); + break; + } + + 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 game_rules; +} 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 new file mode 100644 index 000000000..8c68af30f --- /dev/null +++ b/src/core/modules/engines/engines_gamerules_wrap.cpp @@ -0,0 +1,329 @@ +/** +* ============================================================================= +* 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 "export_main.h" +#include "sp_main.h" +#include "engines_gamerules.h" + +// SDK +#include "game/shared/gamerules.h" + +//--------------------------------------------------------------------------------- +// Forward declarations. +//--------------------------------------------------------------------------------- +void export_game_rules(scope); + + +//--------------------------------------------------------------------------------- +// Declare the _sound module. +//--------------------------------------------------------------------------------- +DECLARE_SP_SUBMODULE(_engines, _gamerules) +{ + def( + "find_game_rules_property_offset", + &find_game_rules_property_offset, + "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 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"); + + 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_rules(_gamerules); +} + + +//----------------------------------------------------------------------------- +// Expose GameRules. +//----------------------------------------------------------------------------- +void export_game_rules(scope _gamerules) +{ + class_ GameRules("GameRules", no_init); + + // 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.def("get_property_color", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Color" + ); + + GameRules.def("get_property_interval", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Interval" + ); + + GameRules.def("get_property_quaternion", + &CGameRulesWrapper::GetProperty, + "Return the value of the given field name.\n\n" + ":rtype: Quaternion" + ); + + 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) + END_CLASS_INFO() +} 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 3f0fea5d1..1ec5e6352 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); 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)