From ea5fab536fa223396ac4a2dd10409f7784acd5d4 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Sat, 2 Oct 2021 20:37:58 +0900 Subject: [PATCH 1/9] Added the ability to add callbacks to ConVar that will be called when ConVar is changed. --- src/core/modules/cvars/cvars.h | 96 +++++++++++++++++++++++++++ src/core/modules/cvars/cvars_wrap.cpp | 20 +++++- 2 files changed, 115 insertions(+), 1 deletion(-) mode change 100644 => 100755 src/core/modules/cvars/cvars.h diff --git a/src/core/modules/cvars/cvars.h b/src/core/modules/cvars/cvars.h old mode 100644 new mode 100755 index bfa2079f2..1eb8c9f5a --- a/src/core/modules/cvars/cvars.h +++ b/src/core/modules/cvars/cvars.h @@ -30,8 +30,22 @@ //----------------------------------------------------------------------------- // Includes. //----------------------------------------------------------------------------- +// C++ +#include +#include + #include "convar.h" + #include "utilities/sp_util.h" +#include "modules/listeners/listeners_manager.h" + + +//----------------------------------------------------------------------------- +// Global ConVar changed callback mapping. +//----------------------------------------------------------------------------- +typedef std::vector ChangedCallbacks; +typedef std::unordered_map ConVarMap; +ConVarMap g_ConVarMap; //----------------------------------------------------------------------------- @@ -117,6 +131,88 @@ class ConVarExt pConVar->m_nFlags &= ~FCVAR_NOTIFY; g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat()); } + + static void ChangedCallback(IConVar* var, const char* pOldValue, float flOldValue) + { + ConVarMap::iterator map_it = g_ConVarMap.find(var->GetName()); + if (map_it == g_ConVarMap.end()) + return; + + ConVar* pConVar = static_cast(var); + + ChangedCallbacks& callables = map_it->second; + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) + { + BEGIN_BOOST_PY() + (*it)(ptr(pConVar), pOldValue, pConVar->GetString()); + END_BOOST_PY_NORET() + } + } + + static void AddChangedCallback(ConVar* pConVar, PyObject* pCallable) + { + // Get the object instance of the callable + object oCallable = object(handle<>(borrowed(pCallable))); + + ChangedCallbacks& callables = g_ConVarMap[pConVar->GetName()]; + if (!callables.size()) + { + if (!installed) + { + g_pCVar->InstallGlobalChangeCallback(ChangedCallback); + installed = true; + } + } + else + { + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) + { + if (is_same_func(oCallable, *it)) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback already registered.") + } + } + + callables.push_back(oCallable); + } + + static void RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable) + { + ConVarMap::iterator map_it = g_ConVarMap.find(pConVar->GetName()); + if (map_it == g_ConVarMap.end()) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + + // Get the object instance of the callable + object oCallable = object(handle<>(borrowed(pCallable))); + + ChangedCallbacks& callables = map_it->second; + for (ChangedCallbacks::iterator it = callables.begin();;) + { + if(it == callables.end()) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + + if (is_same_func(oCallable, *it)) + { + callables.erase(it); + break; + } + else + { + ++it; + } + } + + if (!callables.size()) + { + g_ConVarMap.erase(map_it); + if (!g_ConVarMap.size()) + { + g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); + installed = false; + } + } + } + + static bool installed; }; diff --git a/src/core/modules/cvars/cvars_wrap.cpp b/src/core/modules/cvars/cvars_wrap.cpp index 997d410f6..d96eb4104 100644 --- a/src/core/modules/cvars/cvars_wrap.cpp +++ b/src/core/modules/cvars/cvars_wrap.cpp @@ -45,6 +45,12 @@ extern ICvar* g_pCVar; +//----------------------------------------------------------------------------- +// ConVar extension definition. +//----------------------------------------------------------------------------- +bool ConVarExt::installed = false; + + //----------------------------------------------------------------------------- // Forward declarations. //----------------------------------------------------------------------------- @@ -299,7 +305,19 @@ void export_convar(scope _cvars) &ConVarExt::RemovePublic, "Remove the notify flag and make the console variable no longer public." ) - + + .def("add_changed_callback", + &ConVarExt::AddChangedCallback, + "Add a callable object that will be called when the ConVar is changed.", + args("callable") + ) + + .def("remove_changed_callback", + &ConVarExt::RemoveChangedCallback, + "Remove a callable object that will be called when the ConVar is changed.", + args("callable") + ) + // Special methods... .def("__float__", &ConVar::GetFloat, From 759953f727fac97261e0c9822b2c36fa14a81ea4 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Sat, 2 Oct 2021 21:17:21 +0900 Subject: [PATCH 2/9] Added ConVarChanged decorator class to cvars. --- .../packages/source-python/cvars/__init__.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) mode change 100644 => 100755 addons/source-python/packages/source-python/cvars/__init__.py diff --git a/addons/source-python/packages/source-python/cvars/__init__.py b/addons/source-python/packages/source-python/cvars/__init__.py old mode 100644 new mode 100755 index 66177aede..fdf30f472 --- a/addons/source-python/packages/source-python/cvars/__init__.py +++ b/addons/source-python/packages/source-python/cvars/__init__.py @@ -6,6 +6,8 @@ # >> IMPORTS # ============================================================================= # Source.Python Imports +# Core +from core import AutoUnload # Cvars from _cvars import ConVar from _cvars import _Cvar @@ -24,5 +26,64 @@ # >> ALL DECLARATION # ============================================================================= __all__ = ('ConVar', + 'ConVarChanged', 'cvar', ) + + +# ============================================================================= +# >> CLASSES +# ============================================================================= +class ConVarChanged(AutoUnload): + """ConVarChanged decorator class.""" + + def __init__(self, *convars): + """Store the convars.""" + self._convars = () + self.callback = None + + # Validate convars + if not convars: + raise ValueError('At least one convar is required.') + + _convars = [] + for convar in convars: + if not isinstance(convar, (str, ConVar)): + raise ValueError('Given convar is not ConVar or ConVar name.') + + elif isinstance(convar, str): + convar_name = convar + convar = cvar.find_var(convar_name) + if convar is None: + raise ValueError( + f'"{convar_name}" is not a valid ConVar name.') + + _convars.append(convar) + + self._convars = tuple(_convars) + + def __call__(self, callback): + """Store the callback and add it to convars.""" + # Store the callback + self.callback = callback + + # Loop through all convars + for convar in self._convars: + + # Add the callback + convar.add_changed_callback(self.callback) + + # Return the callback + return self.callback + + def _unload_instance(self): + """Remove the callback from convars.""" + # Was no callback registered? + if self.callback is None: + return + + # Loop through all convars + for convar in self._convars: + + # Remove the callback + convar.remove_changed_callback(self.callback) From 3672a3b2444c5ab704470991e15489f1aec6175f Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Sun, 3 Oct 2021 23:36:55 +0900 Subject: [PATCH 3/9] Fixed incorrect type of ConVarExt::GetMax. --- src/core/modules/cvars/cvars.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/modules/cvars/cvars.h b/src/core/modules/cvars/cvars.h index 1eb8c9f5a..066153bb1 100755 --- a/src/core/modules/cvars/cvars.h +++ b/src/core/modules/cvars/cvars.h @@ -108,7 +108,7 @@ class ConVarExt return fMin; } - static bool GetMax(ConVar* pConVar) + static float GetMax(ConVar* pConVar) { float fMax; pConVar->GetMax(fMax); From 04de099f1a5cae81bf1bedb08ae3d76b527365ab Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Sun, 3 Oct 2021 23:50:45 +0900 Subject: [PATCH 4/9] Added callbacks clean-up. --- src/CMakeLists.txt | 1 + src/core/modules/cvars/cvars.cpp | 209 ++++++++++++++++++++++++++ src/core/modules/cvars/cvars.h | 174 ++------------------- src/core/modules/cvars/cvars_wrap.cpp | 6 - src/core/sp_main.cpp | 4 + 5 files changed, 229 insertions(+), 165 deletions(-) mode change 100644 => 100755 src/CMakeLists.txt create mode 100755 src/core/modules/cvars/cvars.cpp mode change 100644 => 100755 src/core/modules/cvars/cvars_wrap.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt old mode 100644 new mode 100755 index 9bb21297a..889a15441 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -171,6 +171,7 @@ Set(SOURCEPYTHON_CVARS_MODULE_HEADERS ) Set(SOURCEPYTHON_CVARS_MODULE_SOURCES + core/modules/cvars/cvars.cpp core/modules/cvars/cvars_wrap.cpp ) diff --git a/src/core/modules/cvars/cvars.cpp b/src/core/modules/cvars/cvars.cpp new file mode 100755 index 000000000..1d87c0de6 --- /dev/null +++ b/src/core/modules/cvars/cvars.cpp @@ -0,0 +1,209 @@ +/** +* ============================================================================= +* 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 "cvars.h" + + +//----------------------------------------------------------------------------- +// Global ConVar changed callback mapping. +//----------------------------------------------------------------------------- +typedef std::vector ChangedCallbacks; +typedef std::unordered_map ConVarMap; +ConVarMap g_ConVarMap; + + +//----------------------------------------------------------------------------- +// ConVar extension class. +//----------------------------------------------------------------------------- +boost::shared_ptr ConVarExt::__init__(const char* name, const char* value, + const char* description, int flags, object min_value, object max_value) +{ + if (!name || name[0] == '\0') + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "An empty string is not a valid ConVar name.") + + float fMin = 0; + float fMax = 0; + + try { + fMin = extract(min_value); + } + catch (...) { + PyErr_Clear(); + } + + try { + fMax = extract(max_value); + } + catch (...) { + PyErr_Clear(); + } + + ConVar *pConVar = g_pCVar->FindVar(name); + if (!pConVar) + { + ConVar* pConVar = new ConVar(strdup(name), strdup(value), flags, + strdup(description), !min_value.is_none(), fMin, !max_value.is_none(), fMax); + + return boost::shared_ptr(pConVar, &NeverDeleteDeleter); + } + + return boost::shared_ptr(pConVar, &NeverDeleteDeleter); +} + +bool ConVarExt::HasMin(ConVar* pConVar) +{ + float fMin; + return pConVar->GetMin(fMin); +} + +bool ConVarExt::HasMax(ConVar* pConVar) +{ + float fMax; + return pConVar->GetMax(fMax); +} + +float ConVarExt::GetMin(ConVar* pConVar) +{ + float fMin; + pConVar->GetMin(fMin); + return fMin; +} + +float ConVarExt::GetMax(ConVar* pConVar) +{ + float fMax; + pConVar->GetMax(fMax); + return fMax; +} + +void ConVarExt::SetValue(ConVar* pConVar, bool bValue) +{ + pConVar->SetValue(bValue); +} + +void ConVarExt::MakePublic(ConVar* pConVar) +{ + pConVar->m_nFlags |= FCVAR_NOTIFY; + g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat()); +} + +void ConVarExt::RemovePublic(ConVar* pConVar) +{ + pConVar->m_nFlags &= ~FCVAR_NOTIFY; + g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat()); +} + +void ConVarExt::ChangedCallback(IConVar* var, const char* pOldValue, float flOldValue) +{ + ConVarMap::iterator map_it = g_ConVarMap.find(var->GetName()); + if (map_it == g_ConVarMap.end()) + return; + + ConVar* pConVar = static_cast(var); + + ChangedCallbacks& callables = map_it->second; + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) + { + BEGIN_BOOST_PY() + (*it)(ptr(pConVar), pOldValue, pConVar->GetString()); + END_BOOST_PY_NORET() + } +} + +void ConVarExt::AddChangedCallback(ConVar* pConVar, PyObject* pCallable) +{ + // Get the object instance of the callable + object oCallable = object(handle<>(borrowed(pCallable))); + + ChangedCallbacks& callables = g_ConVarMap[pConVar->GetName()]; + if (!callables.size()) + { + if (!installed) + { + g_pCVar->InstallGlobalChangeCallback(ChangedCallback); + installed = true; + } + } + else + { + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) + { + if (is_same_func(oCallable, *it)) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback already registered.") + } + } + + callables.push_back(oCallable); +} + +void ConVarExt::RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable) +{ + ConVarMap::iterator map_it = g_ConVarMap.find(pConVar->GetName()); + if (map_it == g_ConVarMap.end()) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + + // Get the object instance of the callable + object oCallable = object(handle<>(borrowed(pCallable))); + + ChangedCallbacks& callables = map_it->second; + for (ChangedCallbacks::iterator it = callables.begin();;) + { + if(it == callables.end()) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + + if (is_same_func(oCallable, *it)) + { + callables.erase(it); + break; + } + else + { + ++it; + } + } + + if (!callables.size()) + { + g_ConVarMap.erase(map_it); + if (!g_ConVarMap.size()) + { + g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); + installed = false; + } + } +} + +void ConVarExt::ClearCallback() +{ + g_ConVarMap.clear(); + if (installed) + g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); +} + +bool ConVarExt::installed = false; diff --git a/src/core/modules/cvars/cvars.h b/src/core/modules/cvars/cvars.h index 066153bb1..8c9f1e4bb 100755 --- a/src/core/modules/cvars/cvars.h +++ b/src/core/modules/cvars/cvars.h @@ -34,20 +34,15 @@ #include #include +// This is required for accessing m_nFlags without patching convar.h +#define private public #include "convar.h" +#undef private #include "utilities/sp_util.h" #include "modules/listeners/listeners_manager.h" -//----------------------------------------------------------------------------- -// Global ConVar changed callback mapping. -//----------------------------------------------------------------------------- -typedef std::vector ChangedCallbacks; -typedef std::unordered_map ConVarMap; -ConVarMap g_ConVarMap; - - //----------------------------------------------------------------------------- // ConVar extension class. //----------------------------------------------------------------------------- @@ -55,162 +50,23 @@ class ConVarExt { public: static boost::shared_ptr __init__(const char* name, const char* value, - const char* description, int flags, object min_value, object max_value) - { - if (!name || name[0] == '\0') - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "An empty string is not a valid ConVar name.") - - float fMin = 0; - float fMax = 0; - - try { - fMin = extract(min_value); - } - catch (...) { - PyErr_Clear(); - } - - try { - fMax = extract(max_value); - } - catch (...) { - PyErr_Clear(); - } - - ConVar *pConVar = g_pCVar->FindVar(name); - if (!pConVar) - { - ConVar* pConVar = new ConVar(strdup(name), strdup(value), flags, - strdup(description), !min_value.is_none(), fMin, !max_value.is_none(), fMax); - - return boost::shared_ptr(pConVar, &NeverDeleteDeleter); - } - - return boost::shared_ptr(pConVar, &NeverDeleteDeleter); - } - - static bool HasMin(ConVar* pConVar) - { - float fMin; - return pConVar->GetMin(fMin); - } - - static bool HasMax(ConVar* pConVar) - { - float fMax; - return pConVar->GetMax(fMax); - } - - static float GetMin(ConVar* pConVar) - { - float fMin; - pConVar->GetMin(fMin); - return fMin; - } - - static float GetMax(ConVar* pConVar) - { - float fMax; - pConVar->GetMax(fMax); - return fMax; - } - - static void SetValue(ConVar* pConVar, bool bValue) - { - pConVar->SetValue(bValue); - } - - static void MakePublic(ConVar* pConVar) - { - pConVar->m_nFlags |= FCVAR_NOTIFY; - g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat()); - } - - static void RemovePublic(ConVar* pConVar) - { - pConVar->m_nFlags &= ~FCVAR_NOTIFY; - g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat()); - } - - static void ChangedCallback(IConVar* var, const char* pOldValue, float flOldValue) - { - ConVarMap::iterator map_it = g_ConVarMap.find(var->GetName()); - if (map_it == g_ConVarMap.end()) - return; - - ConVar* pConVar = static_cast(var); - - ChangedCallbacks& callables = map_it->second; - for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) - { - BEGIN_BOOST_PY() - (*it)(ptr(pConVar), pOldValue, pConVar->GetString()); - END_BOOST_PY_NORET() - } - } - - static void AddChangedCallback(ConVar* pConVar, PyObject* pCallable) - { - // Get the object instance of the callable - object oCallable = object(handle<>(borrowed(pCallable))); - - ChangedCallbacks& callables = g_ConVarMap[pConVar->GetName()]; - if (!callables.size()) - { - if (!installed) - { - g_pCVar->InstallGlobalChangeCallback(ChangedCallback); - installed = true; - } - } - else - { - for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) - { - if (is_same_func(oCallable, *it)) - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback already registered.") - } - } - - callables.push_back(oCallable); - } + const char* description, int flags, object min_value, object max_value); - static void RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable) - { - ConVarMap::iterator map_it = g_ConVarMap.find(pConVar->GetName()); - if (map_it == g_ConVarMap.end()) - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + static bool HasMin(ConVar* pConVar); + static bool HasMax(ConVar* pConVar); - // Get the object instance of the callable - object oCallable = object(handle<>(borrowed(pCallable))); + static float GetMin(ConVar* pConVar); + static float GetMax(ConVar* pConVar); - ChangedCallbacks& callables = map_it->second; - for (ChangedCallbacks::iterator it = callables.begin();;) - { - if(it == callables.end()) - BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") + static void SetValue(ConVar* pConVar, bool bValue); - if (is_same_func(oCallable, *it)) - { - callables.erase(it); - break; - } - else - { - ++it; - } - } + static void MakePublic(ConVar* pConVar); + static void RemovePublic(ConVar* pConVar); - if (!callables.size()) - { - g_ConVarMap.erase(map_it); - if (!g_ConVarMap.size()) - { - g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); - installed = false; - } - } - } + static void ChangedCallback(IConVar* var, const char* pOldValue, float flOldValue); + static void AddChangedCallback(ConVar* pConVar, PyObject* pCallable); + static void RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable); + static void ClearCallback(); static bool installed; }; diff --git a/src/core/modules/cvars/cvars_wrap.cpp b/src/core/modules/cvars/cvars_wrap.cpp old mode 100644 new mode 100755 index d96eb4104..f4d66b954 --- a/src/core/modules/cvars/cvars_wrap.cpp +++ b/src/core/modules/cvars/cvars_wrap.cpp @@ -45,12 +45,6 @@ extern ICvar* g_pCVar; -//----------------------------------------------------------------------------- -// ConVar extension definition. -//----------------------------------------------------------------------------- -bool ConVarExt::installed = false; - - //----------------------------------------------------------------------------- // Forward declarations. //----------------------------------------------------------------------------- diff --git a/src/core/sp_main.cpp b/src/core/sp_main.cpp index 679ff8f6a..242d278f6 100755 --- a/src/core/sp_main.cpp +++ b/src/core/sp_main.cpp @@ -58,6 +58,7 @@ #include "manager.h" #include "modules/listeners/listeners_manager.h" +#include "modules/cvars/cvars.h" #include "utilities/conversions.h" #include "modules/entities/entities_entity.h" #include "modules/core/core.h" @@ -401,6 +402,9 @@ void CSourcePython::Unload( void ) DevMsg(1, MSG_PREFIX "Clearing convar changed listener...\n"); GetOnConVarChangedListenerManager()->clear(); + DevMsg(1, MSG_PREFIX "Clearing convar changed callbacks...\n"); + ConVarExt::ClearCallback(); + DevMsg(1, MSG_PREFIX "Unhooking all functions...\n"); GetHookManager()->UnhookAllFunctions(); From 3f0734591468fbfbdb8e51059e4e3b97f6f4358c Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Sun, 3 Oct 2021 23:55:48 +0900 Subject: [PATCH 5/9] Changed ConVarExt::ClearCallback. --- src/core/modules/cvars/cvars.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/modules/cvars/cvars.cpp b/src/core/modules/cvars/cvars.cpp index 1d87c0de6..6bcc4add3 100755 --- a/src/core/modules/cvars/cvars.cpp +++ b/src/core/modules/cvars/cvars.cpp @@ -201,9 +201,12 @@ void ConVarExt::RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable) void ConVarExt::ClearCallback() { - g_ConVarMap.clear(); if (installed) + { + g_ConVarMap.clear(); g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); + installed = false; + } } bool ConVarExt::installed = false; From 96145c7d65ce1f48a6ff94188024ab7c32744685 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Mon, 4 Oct 2021 21:58:33 +0900 Subject: [PATCH 6/9] Check if the callback can be called. --- addons/source-python/packages/source-python/cvars/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/source-python/packages/source-python/cvars/__init__.py b/addons/source-python/packages/source-python/cvars/__init__.py index fdf30f472..516a2a380 100755 --- a/addons/source-python/packages/source-python/cvars/__init__.py +++ b/addons/source-python/packages/source-python/cvars/__init__.py @@ -64,6 +64,10 @@ def __init__(self, *convars): def __call__(self, callback): """Store the callback and add it to convars.""" + # Is the callback callable? + if not callable(callback): + raise ValueError('Given callback is not callable.') + # Store the callback self.callback = callback From 94e24badfcd2272e854cf010b1c656e15eac8b7f Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Tue, 5 Oct 2021 00:03:36 +0900 Subject: [PATCH 7/9] Changed to check if ConVar is a valid ConVar. --- .../packages/source-python/cvars/__init__.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/addons/source-python/packages/source-python/cvars/__init__.py b/addons/source-python/packages/source-python/cvars/__init__.py index 516a2a380..f9dba0936 100755 --- a/addons/source-python/packages/source-python/cvars/__init__.py +++ b/addons/source-python/packages/source-python/cvars/__init__.py @@ -48,15 +48,16 @@ def __init__(self, *convars): _convars = [] for convar in convars: - if not isinstance(convar, (str, ConVar)): + if isinstance(convar, str): + convar_name = convar + elif isinstance(convar, ConVar): + convar_name = convar.name + else: raise ValueError('Given convar is not ConVar or ConVar name.') - elif isinstance(convar, str): - convar_name = convar - convar = cvar.find_var(convar_name) - if convar is None: - raise ValueError( - f'"{convar_name}" is not a valid ConVar name.') + convar = cvar.find_var(convar_name) + if convar is None: + raise ValueError(f'"{convar_name}" is not a valid ConVar.') _convars.append(convar) From 6fea4b507e9f71e95e2e0837d7737f90a21874be Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Tue, 5 Oct 2021 00:56:42 +0900 Subject: [PATCH 8/9] Revert "Changed to check if ConVar is a valid ConVar." This reverts commit 94e24badfcd2272e854cf010b1c656e15eac8b7f. --- .../packages/source-python/cvars/__init__.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/addons/source-python/packages/source-python/cvars/__init__.py b/addons/source-python/packages/source-python/cvars/__init__.py index f9dba0936..516a2a380 100755 --- a/addons/source-python/packages/source-python/cvars/__init__.py +++ b/addons/source-python/packages/source-python/cvars/__init__.py @@ -48,16 +48,15 @@ def __init__(self, *convars): _convars = [] for convar in convars: - if isinstance(convar, str): - convar_name = convar - elif isinstance(convar, ConVar): - convar_name = convar.name - else: + if not isinstance(convar, (str, ConVar)): raise ValueError('Given convar is not ConVar or ConVar name.') - convar = cvar.find_var(convar_name) - if convar is None: - raise ValueError(f'"{convar_name}" is not a valid ConVar.') + elif isinstance(convar, str): + convar_name = convar + convar = cvar.find_var(convar_name) + if convar is None: + raise ValueError( + f'"{convar_name}" is not a valid ConVar name.') _convars.append(convar) From 080d8cad384ace6658b128f508a46f6778755276 Mon Sep 17 00:00:00 2001 From: Jonathan <30329245+CookStar@users.noreply.github.com> Date: Tue, 5 Oct 2021 01:03:49 +0900 Subject: [PATCH 9/9] Changed to raise an exception if ConCommand already exists when creating ConVar. --- src/core/modules/cvars/cvars.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/modules/cvars/cvars.cpp b/src/core/modules/cvars/cvars.cpp index 6bcc4add3..0dc945a32 100755 --- a/src/core/modules/cvars/cvars.cpp +++ b/src/core/modules/cvars/cvars.cpp @@ -67,6 +67,11 @@ boost::shared_ptr ConVarExt::__init__(const char* name, const char* valu ConVar *pConVar = g_pCVar->FindVar(name); if (!pConVar) { + // Find if the command already exists + ConCommand* pConCommand = g_pCVar->FindCommand(name); + if (pConCommand) + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "ConCommand already exists.") + ConVar* pConVar = new ConVar(strdup(name), strdup(value), flags, strdup(description), !min_value.is_none(), fMin, !max_value.is_none(), fMax); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy