ConVar - equivalent to RegisterConVarChanges

Please post any questions about developing your plugin here. Please use the search function before posting!
joshtrav
Junior Member
Posts: 5
Joined: Mon Jun 08, 2015 5:28 am
Contact:

ConVar - equivalent to RegisterConVarChanges

Postby joshtrav » Mon Jun 08, 2015 5:35 am

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?
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 08, 2015 6:15 am

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
Image
joshtrav
Junior Member
Posts: 5
Joined: Mon Jun 08, 2015 5:28 am
Contact:

Postby joshtrav » Mon Jun 08, 2015 3:08 pm

Thanks for the info. I think the first option will work just fine. I assume I could then just set the bDontBroadcast value to True in the server_cvar event?
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 08, 2015 3:21 pm

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:

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
Image
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Mon Jun 08, 2015 4:09 pm

satoon101 wrote:Though, hopefully fairly soon, you will just be able to do something more like:

[python]from events.hooks import PreEvent


@PreEvent
def server_cvar(game_event):
# Block the broadcasting of the event to clients
return False[/python]


Yes please!!
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Mon Jun 08, 2015 5:34 pm

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)
joshtrav
Junior Member
Posts: 5
Joined: Mon Jun 08, 2015 5:28 am
Contact:

Postby joshtrav » Tue Jun 09, 2015 3:44 am

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?
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Tue Jun 09, 2015 6:24 am

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. :)
joshtrav
Junior Member
Posts: 5
Joined: Mon Jun 08, 2015 5:28 am
Contact:

Postby joshtrav » Wed Jun 10, 2015 2:08 am

Ayuto, would you still need to hook the GameEventManager to stop the broadcast using the method you posted?
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Wed Jun 10, 2015 6:54 am

The callback gets called everytime a ConVar changes and it doesn't need the NOTIFY flag. But yes, if it has this flag, you would need to hook FireEvent.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 54 guests