I have been browsing the wiki, as well as the source on convars.
https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/src/core/modules/cvars/cvars_wrap_python.cpp
http://wiki.sourcepython.com/pages/cvars
I haven't found anything that would resemble a way to hook a convar change, is there a current wrapper for an equivalent? If not, would it be feasible as a feature request?
ConVar - equivalent to RegisterConVarChanges
If you don't need to stop the change from happening, you could always just add the NOTIFY flag to the ConVar and listen to the event server_cvar.
Outside of that, we do have an experimental branch currently that will allow you to hook exposed methods of a class.
https://github.com/Source-Python-Dev-Team/Source.Python/tree/exposed_function_hooks
Here is an example of its usage:
https://github.com/Source-Python-Dev-Team/Source.Python/commit/408e95b0e0cc3ab25a5551eb46169709ece35d8a#commitcomment-11510933
Outside of that, we do have an experimental branch currently that will allow you to hook exposed methods of a class.
https://github.com/Source-Python-Dev-Team/Source.Python/tree/exposed_function_hooks
Here is an example of its usage:
https://github.com/Source-Python-Dev-Team/Source.Python/commit/408e95b0e0cc3ab25a5551eb46169709ece35d8a#commitcomment-11510933
To set the bDontBroadcast, you will have to hook fire_game_event. Basic event calling does not have that implemented. We do plan on having a PreEvent decorator at some point, probably once the experimental branch is finalized. Currently, you have to do it more like:
Though, hopefully fairly soon, you will just be able to do something more like:
Syntax: Select all
from core import PLATFORM
from events import GameEvent
from events.manager import GameEventManager
from memory import Convention
from memory import DataType
from memory import get_object_pointer
from memory import make_object
from memory.hooks import PreHook
FIRE_EVENT_FUNC = get_object_pointer(
GameEventManager).make_virtual_function(
7 if PLATFORM == 'windows' else 8,
Convention.THISCALL,
(DataType.POINTER, DataType.POINTER, DataType.BOOL),
DataType.VOID
)
@PreHook(FIRE_EVENT_FUNC)
def pre_fire_event(arguments):
game_event = make_object(GameEvent, arguments[1])
if game_event.get_name() == 'server_cvar':
arguments[2] = True
Though, hopefully fairly soon, you will just be able to do something more like:
Syntax: Select all
from events.hooks import PreEvent
@PreEvent
def server_cvar(game_event):
# Block the broadcasting of the event to clients
return False
I would like to take this chance to show another feature of SP, which is already available since a long time. Though, we have improved this feature a few weeks ago.
You can create functions, which have an address in memory, so you can pass them to any function you want. This means that you can create C++ functions with any calling convention on the fly!
You can create functions, which have an address in memory, so you can pass them to any function you want. This means that you can create C++ functions with any calling convention on the fly!
Syntax: Select all
# This example has been made for Windows (CS:S)
import memory
from memory import DataType
from memory import Convention
from memory import Callback
from cvars import cvar
from _cvars import _IConVar
# Get the cvar pointer
cvar_ptr = memory.get_object_pointer(cvar)
# virtual void ICvar::InstallGlobalChangeCallback(FnChangeCallback_t callback) = 0;
InstallGlobalChangeCallback = cvar_ptr.make_virtual_function(
18,
Convention.THISCALL,
[DataType.POINTER, DataType.POINTER],
DataType.VOID
)
# virtual void ICvar::RemoveGlobalChangeCallback(FnChangeCallback_t callback) = 0;
RemoveGlobalChangeCallback = cvar_ptr.make_virtual_function(
19,
Convention.THISCALL,
[DataType.POINTER, DataType.POINTER],
DataType.VOID
)
# Create a function in memory, which can be treated just like a function
# pointer. Awesome, eh? :P
# typedef void ( *FnChangeCallback_t )( IConVar *var, const char *pOldValue, float flOldValue );
@Callback(
Convention.CDECL,
[DataType.POINTER, DataType.STRING, DataType.FLOAT],
DataType.VOID)
def on_cvar_changed(args):
"""Called whenever a ConVar changes."""
convar = memory.make_object(_IConVar, args[0])
old_str_value = args[1]
old_float_value = args[2]
print(convar.get_name(), 'has changed')
def load():
# Install the callback
InstallGlobalChangeCallback(cvar_ptr, on_cvar_changed)
def unload():
# Remove the callback
RemoveGlobalChangeCallback(cvar_ptr, on_cvar_changed)
satoon101 wrote:
Though, hopefully fairly soon, you will just be able to do something more like:Syntax: Select all
from events.hooks import PreEvent
@PreEvent
def server_cvar(game_event):
# Block the broadcasting of the event to clients
return False
This will be very nice, and thanks for the current way as well!
Ayuto wrote:I would like to take this chance to show another feature of SP, which is already available since a long time. Though, we have improved this feature a few weeks ago.
You can create functions, which have an address in memory, so you can pass them to any function you want. This means that you can create C++ functions with any calling convention on the fly!Syntax: Select all
# This example has been made for Windows (CS:S)
import memory
from memory import DataType
from memory import Convention
from memory import Callback
from cvars import cvar
from _cvars import _IConVar
# Get the cvar pointer
cvar_ptr = memory.get_object_pointer(cvar)
# virtual void ICvar::InstallGlobalChangeCallback(FnChangeCallback_t callback) = 0;
InstallGlobalChangeCallback = cvar_ptr.make_virtual_function(
18,
Convention.THISCALL,
[DataType.POINTER, DataType.POINTER],
DataType.VOID
)
# virtual void ICvar::RemoveGlobalChangeCallback(FnChangeCallback_t callback) = 0;
RemoveGlobalChangeCallback = cvar_ptr.make_virtual_function(
19,
Convention.THISCALL,
[DataType.POINTER, DataType.POINTER],
DataType.VOID
)
# Create a function in memory, which can be treated just like a function
# pointer. Awesome, eh? :P
# typedef void ( *FnChangeCallback_t )( IConVar *var, const char *pOldValue, float flOldValue );
@Callback(
Convention.CDECL,
[DataType.POINTER, DataType.STRING, DataType.FLOAT],
DataType.VOID)
def on_cvar_changed(args):
"""Called whenever a ConVar changes."""
convar = memory.make_object(_IConVar, args[0])
old_str_value = args[1]
old_float_value = args[2]
print(convar.get_name(), 'has changed')
def load():
# Install the callback
InstallGlobalChangeCallback(cvar_ptr, on_cvar_changed)
def unload():
# Remove the callback
RemoveGlobalChangeCallback(cvar_ptr, on_cvar_changed)
This seems very involved and powerful, is there a substantial amount of info on the wiki in regards to this that I missed?
We haven't added that to the wiki yet. But here is the source code: https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/addons/source-python/packages/source-python/memory/__init__.py#L77
I can add that to the wiki today.
I can add that to the wiki today.

Return to “Plugin Development Support”
Who is online
Users browsing this forum: No registered users and 52 guests