TF2 run_command hook

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 12:36 am

Hi all. I'm making a TF2 plugin in SourcePython and I'm trying to make a hook using @EntityPreHook for the run_command hook (which should fire every time a player's usercmd is processed if I'm not mistaken). However I keep getting a nasty error:

Code: Select all

Traceback (most recent call last):
  File '../addons/source-python/packages/source-python/entities/hooks.py', line 184, in on_entity_created
    _waiting_entity_hooks.initialize(index)
  File '../addons/source-python/packages/source-python/entities/hooks.py', line 170, in initialize
    if hook.initialize(entity):
  File '../addons/source-python/packages/source-python/entities/hooks.py', line 131, in initialize
    self.hooked_function = getattr(entity, self.function)
  File '../addons/source-python/packages/source-python/entities/entity.py', line 102, in __getattr__
    raise AttributeError('Attribute '{0}' not found'.format(attr))
 
AttributeError: Attribute 'run_command' not found


Here's the really minimal code I was testing with:

Syntax: Select all

from entities.hooks import EntityCondition, EntityPreHook
from players import UserCmd
from memory import make_object

@EntityPreHook(EntityCondition.is_player, "run_command")
def classmenu(stack):
print(make_object(UserCmd, stack[1]).buttons)


What's going wrong here?

(I'm using the latest version of SourcePython)
Last edited by L'In20Cible on Wed Jul 13, 2016 3:17 am, edited 1 time in total.
Reason: [code] → [python]
User avatar
L'In20Cible
Project Leader
Posts: 1536
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: TF2 run_command hook

Postby L'In20Cible » Wed Jul 13, 2016 3:11 am

I guess this: https://github.com/Source-Python-Dev-Te ... ini#L39-43

Should be moved into ../orangebox/CBasePlayer.ini as it is most likely the same for all OB games. I will have to update some of my servers before confirming it is and push that but try to replace the content of that file with the following:

Syntax: Select all

# ../orangebox/CBasePlayer.ini

[function]

[[increment_frag_count]]
identifier_windows = 55 8B EC 8B 45 08 01 81 F8 0C 00 00
identifier_linux = _ZN11CBasePlayer18IncrementFragCountEi
arguments = INT

[[increment_death_count]]
identifier_windows = 55 8B EC 8B 45 08 01 81 FC 0C 00 00
identifier_linux = _ZN11CBasePlayer19IncrementDeathCountEi
arguments = INT


[virtual_function]

# _ZN11CBasePlayer11Weapon_DropEP17CBaseCombatWeaponPK6VectorS4_
[[drop_weapon]]
offset_linux = 264
offset_windows = 263
arguments = POINTER, POINTER, POINTER

# _ZN11CBasePlayer8PreThinkEv
[[pre_think]]
offset_linux = 333
offset_windows = 332

# _ZN11CBasePlayer9PostThinkEv
[[post_think]]
offset_linux = 334
offset_windows = 333

# _ZN11CBasePlayer16PlayerRunCommandEP8CUserCmdP11IMoveHelper
[[run_command]]
offset_linux = 420
offset_windows = 419
arguments = POINTER, POINTER
User avatar
satoon101
Project Leader
Posts: 2725
Joined: Sat Jul 07, 2012 1:59 am

Re: TF2 run_command hook

Postby satoon101 » Wed Jul 13, 2016 3:15 am

No it isn't, at least not as of the time this was added:
https://github.com/Source-Python-Dev-Te ... yer.ini#L4

We do need to add it for all engines/games, though. I am finally getting up and running at my new place, but my computer has been offline for 2 months and has a lot of catching up to do before I can look to add those in.
Image
User avatar
L'In20Cible
Project Leader
Posts: 1536
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: TF2 run_command hook

Postby L'In20Cible » Wed Jul 13, 2016 4:04 am

You are right, HL2:MP/DOD:S are one offset lesser than CS:S/TF2. I've pushed for those 2 missing games, don't have updated servers for the others.
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 2:44 pm

So wait, was the Python binding for CBasePlayer::PlayerRunCommand missing in the TF2 build but not in the others? That explains why I saw a forum thread about it working in HL2DM... I assumed I was just doing it wrong :P
User avatar
Ayuto
Project Leader
Posts: 2210
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: TF2 run_command hook

Postby Ayuto » Wed Jul 13, 2016 3:00 pm

Yep, that was the reason.
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 4:03 pm

Just tried it with the new build, when I added a puppet bot to test it (I was too lazy to actually connect to the server) it segfaults. Give me a moment to attach a debug.log
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 5:11 pm

Sorry for the delay:
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 5:12 pm

Probably should have mentioned this earlier, but I'm on Linux (Ubuntu 14.04). I do have two other plugins on my testing server (TFTrue and TF2Items) but looking at the stack trace they're definitely not the culprits.
User avatar
Ayuto
Project Leader
Posts: 2210
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: TF2 run_command hook

Postby Ayuto » Wed Jul 13, 2016 5:20 pm

Looks like Sourcemod is also hooking this method and now they are conflicting when calling make_object().
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 5:23 pm

Interesting; I'll take out Sourcemod for the time and see if it works
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 5:32 pm

Actually, I'll just whip up a clean new server to test it with. Can't do that right now though.
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 8:48 pm

No luck even on a clean server without Sourcemod or any of that:
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Wed Jul 13, 2016 10:39 pm

I should probably open this as an issue on Github instead of here
User avatar
L'In20Cible
Project Leader
Posts: 1536
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: TF2 run_command hook

Postby L'In20Cible » Thu Jul 14, 2016 4:45 am

What if, instead of using EntityCondition.is_player, you try with EntityCondition.is_human_player and you actually goes on the server yourself instead of adding bots?
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Thu Jul 14, 2016 2:35 pm

Stranger and stranger. It works perfectly fine like that, but adding a bot still crashes it even though it's using is_human_player now (which means the hook shouldn't even get called for a bot). It's only when this plugin is loaded so it isn't a general bug in SP or anything. NextBots don't do this, just puppet bots. Not a big deal, just somewhat strange.
User avatar
L'In20Cible
Project Leader
Posts: 1536
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: TF2 run_command hook

Postby L'In20Cible » Thu Jul 14, 2016 2:57 pm

quartata wrote:even though it's using is_human_player now (which means the hook shouldn't even get called).
That's not right. The hook will gets called if both classes share the same address in their dispatch table. The EntityCondition only makes sure that the address is retrieved from an human player before registering the hook but if both classes are sharing the same pointer, it will get fired no matter what the actual "this" pointer is (done this way so you can fully control which method to hook in case of multiple inheritances but filtering the calls, is your responsability).

Now it is time to debug, what gets printed to the console before it crashes?

Syntax: Select all

from entities.hooks import EntityCondition, EntityPreHook
from players import UserCmd
from memory import make_object

@EntityPreHook(EntityCondition.is_human_player, 'run_command')
def classmenu(stack):
print('Callback executed...')
print('Arguments =', list(stack))
usercmd = make_object(UserCmd, stack[1])
print('UserCmd =', usercmd)
print('Buttons =', usercmd.buttons)


Additional question, does it crashes even if you didn't join the server first? In such case, the hook should not be registered so if it does, we may have to add a specific check in either the hook API or the conversion functions which may get a NULL pointer somewhere for those specific bots.

Also, I originally proposed EntityCondition.is_human_player cause I thought the bot class may override that method and pass a CBotCmd instance instead of a CUserCmd.
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Thu Jul 14, 2016 3:32 pm

It does not crash if I don't join the server first. When I do join, it prints the Callback executed and the Arguments before crashing. So the bots using a different class for their usercmd seems plausible; it's obviously crashing when dereferencing the pointer to the usercmd.
User avatar
L'In20Cible
Project Leader
Posts: 1536
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: TF2 run_command hook

Postby L'In20Cible » Thu Jul 14, 2016 3:36 pm

Yeah, I think so. What if you use the following:

Syntax: Select all

from entities.hooks import EntityCondition, EntityPreHook
from players.bots import BotCmd
from players import UserCmd
from players.entity import Player
from memory import make_object

@EntityPreHook(EntityCondition.is_player, "run_command")
def classmenu(stack):
player = make_object(Player, stack[0])
if player.is_fake_client():
cls = BotCmd
else:
cls = UserCmd
usercmd = make_object(cls, stack[1])
print(usercmd.buttons)
User avatar
quartata
Member
Posts: 77
Joined: Wed Jun 22, 2016 11:49 pm

Re: TF2 run_command hook

Postby quartata » Thu Jul 14, 2016 3:41 pm

Did you mean

Syntax: Select all

from players.bots import BotCmd
?

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 58 guests