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)