Page 1 of 1

Hook AirAccelerate

Posted: Sun Dec 01, 2019 12:08 pm
by InvisibleSoldiers
I'm trying to get function parameters inside CGameMovement::AirAccelerate through @PreHook, the function itself hooks properly but getting parameters unclear.

CGameMovement::AirAccelerate( Vector& wishdir, float wishspeed, float accel ): https://github.com/ValveSoftware/source ... .cpp#L1707

Syntax: Select all

from memory import find_binary
from memory import Convention
from memory import DataType
from memory.hooks import PreHook


SERVER = find_binary('server')
AIRACCELERATE = SERVER['_ZN13CGameMovement13AirAccelerateER6Vectorff'].make_function(
Convention.THISCALL,
(DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
DataType.VOID
)

# ACCELERATE = SERVER['_ZN13CGameMovement10AccelerateER6Vectorff'].make_function(
# Convention.THISCALL,
# (DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
# DataType.VOID
#)

@PreHook(AIRACCELERATE)
def pre_hook_airaccelerate(stack_data):
print(stack_data[0])
print(stack_data[1])
print(stack_data[2])

stack_data[0] = _memory.Pointer (CGameMovement::AirAccelerate)
stack_data[1] = NaN
stack_data[2] = wishspeed (CGameMovement::AirAccelerate)

Why did 'wishspeed' and 'accel' switch index places and why is 'accel' NaN

Re: Hook AirAccelerate

Posted: Sun Dec 01, 2019 1:20 pm
by L'In20Cible

Syntax: Select all

AIRACCELERATE = SERVER['_ZN13CGameMovement13AirAccelerateER6Vectorff'].make_function(
Convention.THISCALL,
(DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
DataType.VOID
)

Should be:

Syntax: Select all

AIRACCELERATE = SERVER['_ZN13CGameMovement13AirAccelerateER6Vectorff'].make_function(
Convention.THISCALL,
# this wishdir wishspeed accel
(DataType.POINTER, DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
DataType.VOID
)

Re: Hook AirAccelerate

Posted: Sun Dec 01, 2019 1:25 pm
by InvisibleSoldiers
Edit

Re: Hook AirAccelerate

Posted: Sun Dec 01, 2019 1:51 pm
by InvisibleSoldiers
L'In20Cible wrote:

Syntax: Select all

AIRACCELERATE = SERVER['_ZN13CGameMovement13AirAccelerateER6Vectorff'].make_function(
Convention.THISCALL,
(DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
DataType.VOID
)

Should be:

Syntax: Select all

AIRACCELERATE = SERVER['_ZN13CGameMovement13AirAccelerateER6Vectorff'].make_function(
Convention.THISCALL,
# this wishdir wishspeed accel
(DataType.POINTER, DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
DataType.VOID
)

I did it early but the error is still remaining because i guess Source.Python has a bag with AutoUnload hooks, need full server restart to load next version of the plugin, because 'sp plugin reload ' on existing plugin with the hook leads to some error and full server restart (maybe changelevel) is requred.

Re: Hook AirAccelerate

Posted: Sun Dec 01, 2019 2:12 pm
by L'In20Cible
InvisibleSoldiers wrote:I did it early but the error is still remaining because i guess Source.Python has a bag with AutoUnload hooks, need full server restart to load next version of the plugin, because 'sp plugin reload ' on existing plugin with the hook leads to some error and full server restart (maybe changelevel) is requred.

Not sure what you mean by a bag with AutoUnload but, the fact you have to reboot your server is normal. When an address is hooked for the first time, a hook is installed that points to our internal handler and it is never uninstalled. When you unload your plugin, your callback is removed but the hook remains in place so if you want to change the prototype of that hook, you must indeed reboot your server.

EDIT: In fact, if you really wanted to you could call:

Syntax: Select all

AIRACCELERATE._delete_hook()


Before your @PreHook decorator and it would apply your changes. However, that method is private for a reason and you should not use it for a public plugin as it could cause conflict with other addons. Take for example the following scenario:

  • Source.Python installs a hook on SomeFunction().
  • SourceMod installs a hook on that same function.
  • Source.Python uninstalls its hook.
  • SourceMod attempts to call the original function, which would either crash or never forward to the real function as they are calling Source.Python's handler resulting into undefined behaviour.

Basically, once a hook have been installed it has to remain to preserve the calling chain, otherwise it would break the relation between everyone hooking the same addresses, etc. Now well, perhaps Source.Python could update the hook, but I believe this would be a waste of effort. I mean, a prototype should never change at run-time, so if you made a mistake then you must reboot.