[CS:S] JumpStats

Release your plugins here!
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

[CS:S] JumpStats

Postby InvisibleSoldiers » Thu Dec 19, 2019 6:47 pm

Improved version of SSJ with various bug fixes and new features.
All features and fixes are listed below.

Features and improvements:
Reworked understanding of a jump and its stats.
In the AlKaTrAz's plugin, jump is a ticks in air after you pressed JUMP and a next jump tick on ground.
It is stats from previous jump + 1 tick in current jump and printing as stats at the moment or in other words at the next optional jump.
Also him plugin ignores first jump tick at all that happens on ground when you took prespeed and this is a starting point to next jump tick inclusive.
I remember that one tick on ground when you pressed JUMP in it and didn't press JUMP in previous tick is a tick which ignored by game movement code as 'friction tick' and will be replaced to 'air' tick.
Bunnyhop is based on this.
So, if we jumped in first time and didn't press JUMP to perform second, does it mean that we are not deserving to see related stats for it, because the jump not is a jump according AlKaTrAz.
No, we should see the stats anyway, because it still remains a jump.
And the new plugin solved this problem, it counts stats as it should. JUMP to LANDING. It may be confused but if we want to see stats for usual 6th jump, we should see its jump number as 5 and subtract 1 tick from statistics where it is used, so yes, it is actually 5th jump, and ending 6th jump itself is a moment at 7th jump in AlkATraZ's SSJ.

Printing stats to HUD
Merged and realised main idea of 'JHUD' plugin into one
Now you can view jump stats on HUD, in chat, or in both.
Also, you can select yourself HUD position with integrated tool for it.
Only strafe speed concept for the a whole jump declined.

Reogranized menu
Reorganized menu for comfortable tweeking HUD and chat preferences.

Prespeed and Friction
Added 'Prespeed' feature and option into menu which allows you to see speed on first jump when you're playing 'sixth', 'every sixth' or 'every' modes with turned off 'Speed' option for other jumps.
Added 'Friction' option in chat preferences, which allows you to see friction time between jumps.

Better configuration
Server owners can easily configure almost all options in one single file named 'jumpstats.conf'
Format rules and options are listed here https://github.com/invisiblesoldiers/Ju ... figuration

Hooks
The plugin hooks few functions of CGameMovement. But don't worry, the signatures used for locating them seem stable when it goes to game updates.
CGameMovement::AirAccelerate hook is there to access some movement data essential for stats determination, this is done to simplify things overall by avoiding external reconstruction of the code already present in game's internals (this was the approach in the AlkATraZ's older SSJ plugin).
CGameMovement::Friction hook serves as an easy method of detecting non-bhop landings.
CameMovement::GetAirSpeedCap for getting the exact AirSpeedCap value instead hardcoded 30.0.

Welcome message
Added sending a welcome message to a new connected player, linked with him preferences.

Fixes
Fixed printing jump stats to spectators when a spectator saw wrong numbers if him mode preference was different that him target.
Fixed ignoring first tick after prespeed.
Fixed shifting a first strafe tick to previous jump. It happenned when you pressed JUMP being on ground. Logically and correctly take this tick as the start of a new jump matching game movement code.
Fixed counting strafes when you was in air but didn't press JUMP before it being on ground. The plugin is about jumps and not about accidentally flying.
Fixed all code leading to float division by zero.

Links
Github (you can download the plugin here): https://github.com/invisiblesoldiers/JumpStats
SSJ: Advanced: https://forums.alliedmods.net/showthread.php?t=287039
JHUD: https://github.com/blankbhop/jhud
Steam: https://steamcommunity.com/id/hhrhhrhrhr/

Credits
Thank you to Πιντιμπικού for all-around help.
Thank you to AlkATraZ (†) for awesome SSJ plugin.
Last edited by InvisibleSoldiers on Sun Dec 22, 2019 8:47 am, edited 1 time in total.
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 8:45 am

Question to L'In20Cible or Ayuto. Why the windows signatures CGameMovement::AirAccelerate ('55 8B EC 51 56 8B F1 8B 46 04') and CGameMovement::Friction ('55 8B EC F3 0F 10 1D ? ? ? ? 83 EC 08 56 8B F1 8B 4E 04') lead to server crash. I pass these raw strings to the binary 'server' and create function from it through 'make_function'.
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 4:09 pm

InvisibleSoldiers wrote:Question to L'In20Cible or Ayuto. Why the windows signatures CGameMovement::AirAccelerate ('55 8B EC 51 56 8B F1 8B 46 04') and CGameMovement::Friction ('55 8B EC F3 0F 10 1D ? ? ? ? 83 EC 08 56 8B F1 8B 4E 04') lead to server crash. I pass these raw strings to the binary 'server' and create function from it through 'make_function'.

I've looked at your code just now, and there is a lot of things wrong.

First of all, signatures must be hex representation, so the following:

Syntax: Select all

'55 8B EC 51 56 8B F1 8B 46 04'


Should be:

Syntax: Select all

b'\x55\x8B\xEC\x51\x56\x8B\xF1\x8B\x46\x04'


Wildcarded bytes are represented by 2A, not ?. So the following:

Syntax: Select all

'55 8B EC F3 0F 10 1D ? ? ? ? 83 EC 08 56 8B F1 8B 4E 04'


Should be:

Syntax: Select all

b'\x55\x8B\xEC\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x83\xEC\x08\x56\x8B\xF1\x8B\x4E\x04'


I can also notice that there are a lot of undefined names on Windows. E.g. friction_signature and getairspeedcap_signature are only defined on Linux, etc. I haven't tested nor looked in the binaries if your signatures are valid/unique, though. But for the reasons mentioned above your code should not even loads and raise so it crashing is surprising to me.

To be honest, there is absolutely no reason not to use TypeManager.create_type_from_dict or even better from a file and let it to its work instead. :wink:
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 6:30 pm

L'In20Cible wrote:
InvisibleSoldiers wrote:To be honest, there is absolutely no reason not to use TypeManager.create_type_from_dict or even better from a file and let it to its work instead. :wink:

Can you explain how to properly create the type using this, it is a bit hard to read for me, i tried:

Syntax: Select all

manager = TypeManager()
gamemovement = {
'_binary': 'server',
'function': {
'AIRACCELERATE': {
'identifier': aa_signature,
'args': (DataType.POINTER, DataType.POINTER, DataType.FLOAT, DataType.FLOAT),
'return_type': DataType.VOID,
'convention': Convention.THISCALL
},
'FRICTION': {
'identifier': friction_signature,
'args': (DataType.POINTER, ),
'return_type': DataType.VOID,
'convention': Convention.THISCALL
}
},
'player_pointer': manager.pointer_attribute('CBasePlayer', player_offset)
}
if PLATFORM == 'linux':
gamemovement['function']['GETAIRSPEEDCAP'] = {
'identifier': getairspeedcap_signature,
'args': (DataType.POINTER, ),
'return_type': DataType.FLOAT,
'convention': Convention.THISCALL
}
elif PLATFORM == 'windows':
gamemovement['virtual_function']['GETAIRSPEEDCAP'] = {
'offset': getairspeedcap_offset,
'args': (DataType.POINTER, ),
'return_type': DataType.FLOAT,
'convention': Convention.THISCALL
}
GameMovement = manager.create_type_from_dict('GameMovement', gamemovement)

ValueError: _binary was not specified

Edit: OK, i understood, '_binary' should have been renamed to 'binary'
But some problems with 'player_pointer':

Syntax: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
File "../addons/source-python/plugins/jumpstats/jumpstats.py", line 51, in post_friction
player = PLAYERS[index_from_pointer(game_movement.player_pointer)]

AttributeError: 'GameMovement' object has no attribute 'player_pointer'
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 6:40 pm

Syntax: Select all

'_binary': 'server',


Should be:

Syntax: Select all

'binary': 'server',
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 6:42 pm

L'In20Cible wrote:

Syntax: Select all

'_binary': 'server',


Should be:

Syntax: Select all

'binary': 'server',

Edit
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 6:49 pm

InvisibleSoldiers wrote:But some problems with 'player_pointer':

Syntax: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
File "../addons/source-python/plugins/jumpstats/jumpstats.py", line 51, in post_friction
player = PLAYERS[index_from_pointer(game_movement.player_pointer)]

AttributeError: 'GameMovement' object has no attribute 'player_pointer'


You should bind it to the class yourself:

Syntax: Select all

gamemovement.player_pointer = manager.pointer_attribute('CBasePlayer', player_offset)


Or, set the following structure in your dictionary:

Syntax: Select all

[pointer_attribute]
[[player_pointer]]
type = POINTER
offset = 4
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 6:56 pm

L'In20Cible wrote:
InvisibleSoldiers wrote:

Syntax: Select all

[pointer_attribute]
[[player_pointer]]
type = POINTER
offset = 4


Syntax: Select all

'pointer_attribute': {
'player_pointer': {
'type': DataType.POINTER,
'offset': 0x4
}
}


Syntax: Select all

File "../addons/source-python/packages/source-python/memory/helpers.py", line 63, in is_native
return hasattr(Type, type_name.upper())

AttributeError: 'DataType' object has no attribute 'upper'
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 7:04 pm

InvisibleSoldiers wrote:AttributeError: 'DataType' object has no attribute 'upper'[/syntax]

Syntax: Select all

'POINTER'
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 7:08 pm

L'In20Cible wrote:
InvisibleSoldiers wrote:AttributeError: 'DataType' object has no attribute 'upper'[/syntax]

Syntax: Select all

'POINTER'

Syntax: Select all

ValueError: Conversion from "Pointer" (<_memory.Pointer object at 0xeced29e0>) to "Index" failed.

Early i did it through Player() object to get index: PLAYERS[Player().index]
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 7:27 pm

Full traceback?
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 7:33 pm

L'In20Cible wrote:Full traceback?

Syntax: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
File "../addons/source-python/plugins/jumpstats/jumpstats.py", line 51, in post_friction
player = PLAYERS[index_from_pointer(game_movement.player_pointer)]

ValueError: Conversion from "Pointer" (<_memory.Pointer object at 0xe82fe0b0>) to "Index" failed.
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 7:45 pm

Btw you don't know what's wrong?

Syntax: Select all

print(get_interface('server_srv.so', 'GameMovement001'))


Syntax: Select all

File "../addons/source-python/plugins/jumpstats/config/__init__.py", line 186, in <module>
print(get_interface('server_srv.so', 'GameMovement001'))

ValueError: Unable to load library 'server_srv.so'
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 7:47 pm

The this pointer register is being reused during the call, making your game_movement invalid because stack_data[0] is a local pointer that has been freed when exiting the original function call. Mostly why you are crashing, actually. Either store the this pointer from the pre hook and use it in the post, or handle the call yourself if your code absolutely need to be executed post call:

Syntax: Select all

from memory import *
from memory.hooks import *

friction = find_binary('server')[b'\x55\x8B\xEC\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x83\xEC\x08\x56\x8B\xF1\x8B\x4E\x04'].make_function(
Convention.THISCALL, (DataType.POINTER, ),
DataType.VOID
)

@PreHook(friction)
def pre_friction(stack):
ret = friction.call_trampoline(*stack)

# ... your code ...

return ret
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 7:51 pm

InvisibleSoldiers wrote:Btw you don't know what's wrong?

Syntax: Select all

print(get_interface('server_srv.so', 'GameMovement001'))


Syntax: Select all

File "../addons/source-python/plugins/jumpstats/config/__init__.py", line 186, in <module>
print(get_interface('server_srv.so', 'GameMovement001'))

ValueError: Unable to load library 'server_srv.so'

I guess you need 'bin/ser..'.
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 8:00 pm

L'In20Cible wrote:The this pointer register is being reused during the call, making your game_movement invalid because stack_data[0] is a local pointer that has been freed when exiting the original function call. Mostly why you are crashing, actually. Either store the this pointer from the pre hook and use it in the post, or handle the call yourself if your code absolutely need to be executed post call:

Syntax: Select all

from memory import *
from memory.hooks import *

friction = find_binary('server')[b'\x55\x8B\xEC\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x83\xEC\x08\x56\x8B\xF1\x8B\x4E\x04'].make_function(
Convention.THISCALL, (DataType.POINTER, ),
DataType.VOID
)

@PreHook(friction)
def pre_friction(stack):
ret = friction.call_trampoline(*stack)

# ... your code ...

return ret

Why does it work then?

Syntax: Select all

manager.register_converter('CBasePlayer', lambda pointer: make_object(Player, pointer))
player = manager.pointer_attribute('CBasePlayer', player_offset) inside GameMovement
@PostHook(GameMovement.FRICTION)
def post_friction(stack_data, ret):
game_movement = make_object(GameMovement, stack_data[0])
player = PLAYERS[game_movement.player.index]
print(player.index)
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 8:08 pm

L'In20Cible wrote:
InvisibleSoldiers wrote:Btw you don't know what's wrong?

Syntax: Select all

print(get_interface('server_srv.so', 'GameMovement001'))


Syntax: Select all

File "../addons/source-python/plugins/jumpstats/config/__init__.py", line 186, in <module>
print(get_interface('server_srv.so', 'GameMovement001'))

ValueError: Unable to load library 'server_srv.so'

I guess you need 'bin/ser..'.

Syntax: Select all

ValueError: Unable to load library 'bin/server_srv.so'.
User avatar
L'In20Cible
Project Leader
Posts: 1335
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [CS:S] JumpStats

Postby L'In20Cible » Sun Dec 22, 2019 8:09 pm

InvisibleSoldiers wrote:Why does it work then?

Syntax: Select all

manager.register_converter('CBasePlayer', lambda pointer: make_object(Player, pointer))
player = manager.pointer_attribute('CBasePlayer', player_offset) inside GameMovement
@PostHook(GameMovement.FRICTION)
def post_friction(stack_data, ret):
game_movement = make_object(GameMovement, stack_data[0])
player = PLAYERS[game_movement.player.index]
print(player.index)

Because CBasePlayer is just wrapping the pointer, and not validating it whatsoever. The fact it "work" is random and this is actually called; undefined behaviour. Actually it can't work, since your CBasePlayer instance is wrapping a NULL pointer. Run this code:

Syntax: Select all

from memory import *
from memory.hooks import *

func = find_binary('server')[b'\x55\x8B\xEC\xF3\x0F\x10\x1D\x2A\x2A\x2A\x2A\x83\xEC\x08\x56\x8B\xF1\x8B\x4E\x04'].make_function(
Convention.THISCALL, (DataType.POINTER, ),
DataType.VOID
)

@PreHook(func)
def pre_friction(stack):
print('Pre:', stack[0].address, stack[0].get_pointer(4).address)

@PostHook(func)
def post_friction(stack, ret):
print('Post:', stack[0].address, stack[0].get_pointer(4).address)


Result:

Syntax: Select all

Pre: 1681373248 487443176
Post: 487443176 0

Basically, your this pointer in the post-hook has been reused by CGameMovement::pl. So when you wrap stack_data[0] as a CGameMovement, you are basically wrapping a CCSPlayer pointer, then you are retrieving a random address that you wrap as a CBasePlayer, etc.

InvisibleSoldiers wrote:
L'In20Cible wrote:
InvisibleSoldiers wrote:Btw you don't know what's wrong?

Syntax: Select all

print(get_interface('server_srv.so', 'GameMovement001'))


Syntax: Select all

File "../addons/source-python/plugins/jumpstats/config/__init__.py", line 186, in <module>
print(get_interface('server_srv.so', 'GameMovement001'))

ValueError: Unable to load library 'server_srv.so'

I guess you need 'bin/ser..'.

Syntax: Select all

ValueError: Unable to load library 'bin/server_srv.so'.

Try without _srv suffix.
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 8:18 pm

Syntax: Select all

@PreHook(GameMovement.AIRACCELERATE)
def pre_airaccelerate(stack_data):
game_movement = make_object(GameMovement, stack_data[0])
index = index_from_pointer(game_movement.player_pointer)
player = PLAYERS[index]

[SP] Caught an Exception:
Traceback (most recent call last):
File "../addons/source-python/plugins/jumpstats/jumpstats.py", line 38, in pre_airaccelerate
index = index_from_pointer(game_movement.player_pointer)

ValueError: Conversion from "Pointer" (<_memory.Pointer object at 0xe81ddd10>) to "Index" failed.


Syntax: Select all

'pointer_attribute': {
'player_pointer': {
'type': 'POINTER',
'offset': 4
}
}
User avatar
InvisibleSoldiers
Senior Member
Posts: 114
Joined: Fri Mar 15, 2019 6:08 am

Re: [CS:S] JumpStats

Postby InvisibleSoldiers » Sun Dec 22, 2019 8:27 pm

L'In20Cible wrote:Try without _srv suffix.


Still the error.

Return to “Plugin Releases”

Who is online

Users browsing this forum: No registered users and 2 guests