Skip to main content

Unified SDK for Rocket League save file data extraction, Stats API WebSocket client, tracker.gg stats, process detection, input (keyboard/controller), and GUI overlay toolkit.

Project description

Nixwrap

Unified Python SDK for Rocket League: save file data extraction, Stats API WebSocket client, tracker.gg stats, process detection, keyboard/controller input, and a reusable GUI/overlay toolkit.

Built because EAC made traditional plugin development for online matches harder. Intended for streamers, tool developers, and anyone who wants RL data in Python.

pip install git+https://github.com/nixvio64/nixwrap

# With optional extras:
pip install "nixwrap[tracker] @ git+https://github.com/nixvio64/nixwrap"   # tracker.gg
pip install "nixwrap[gui] @ git+https://github.com/nixvio64/nixwrap"       # overlay / GUI
pip install "nixwrap[input] @ git+https://github.com/nixvio64/nixwrap"     # keyboard + controller
pip install "nixwrap[all] @ git+https://github.com/nixvio64/nixwrap"      # everything

Modules

Module Purpose Requires
nixwrap.save_file Decrypt + extract data from .save files pycryptodome
nixwrap.process Detect running RL (Steam vs Epic) psutil
nixwrap.stats Live Stats API WebSocket events -
nixwrap.tracker tracker.gg player rank/stats curl-cffi (optional)
nixwrap.input Keyboard, Xbox, DualSense hotkey detection dualsense-controller, keyboard (optional)
nixwrap.gui Overlay/GUI toolkit PySide6 (optional)
nixwrap.utils Constants and helpers -

Quick Start

0. Edit your DefaultStatsAPI.ini

Found at <RL Install Dir>\TAGame\Config\DefaultStatsAPI.ini set PacketSendRate value to something like 20 (1-120).

1. Save File Data Extraction

from nixwrap.save_file import load, find_save_file

# Auto-find the active save file
path = find_save_file()
save = load(path)

# Camera
print(save.camera.fov)           # 110.0
print(save.camera.stiffness)     # 0.55

# Controls (keyboard + gamepad)
print(save.controls.jump)                    # "SpaceBar"
print(save.gamepad_bindings.boost)           # "XboxTypeS_RightShoulder"

# Raw bindings for custom inspection
for b in save.gamepad_bindings.raw_bindings:
    print(f"  {b['Action']} -> {b['Key']}")

# Stats
print(save.stats.wins)           # 1234
print(save.xp.level)             # 27
print(save.xp.total_xp)          # 348223

# Skill data per playlist
for pid, skill in save.skills.items():
    print(f"Playlist {pid}: matches={skill.matches_played}, tier={skill.tier}")

# Inventory
for item in save.inventory:
    print(f"Product {item.product_id} (series {item.series_id})")

# Settings
print(save.video.res_width, save.video.res_height)
print(save.gameplay.controller_deadzone)
print(save.sound.master_volume)

# Quick chats, loadout sets, season, achievements, etc.
print(len(save.quick_chats), "quick chat bindings")
print(len(save.loadout_sets), "loadout presets")

2. Process Detection

from nixwrap.process import find_rocket_league, is_rocket_league_focused

rl = find_rocket_league()
if rl:
    print(f"PID: {rl.pid}")
    print(f"Platform: {rl.platform.value}")      # steam or epic
    print(f"Root dir: {rl.root_dir}")
    print(f"Save path: {rl.save_data_path}")

if is_rocket_league_focused():
    print("RL window has focus")

3. Input Detection (Keyboard + Controller)

from nixwrap.input import (
    is_hotkey_pressed, is_key_pressed,
    get_xinput_state, XINPUT_A,
    setup_dualsense, start_dualsense_monitor,
    get_button_display,
)

# Keyboard
if is_key_pressed("tab"):
    print("Tab is held")

# XInput (Xbox / DS4 via DS4Windows)
state = get_xinput_state()
if state and state.is_pressed(XINPUT_A):
    print("A button pressed")

# DualSense (PS5)
controller = setup_dualsense()       # auto-finds bundled hidapi.dll
start_dualsense_monitor()            # background auto-reconnect

# Unified hotkey check (InGameRank-compatible config format)
config = {"is_controller": True, "controller_type": "xinput",
          "controller_button": XINPUT_A}
if is_hotkey_pressed(config):
    print("Hotkey held!")

# Button display names
print(get_button_display("xinput", XINPUT_A))           # "A"
print(get_button_display("dualsense", 0))               # "Cross"

4. Stats API (Live Events)

from nixwrap.stats import StatsClient

client = StatsClient()

# Callback mode
client.on("GoalScored", lambda evt: print(f"GOAL! {evt.scorer.name}"))
client.on("StatfeedEvent", lambda evt: print(f"{evt.main_target.name}: {evt.stat_type}"))
client.on_event(lambda evt: print(f"[{evt.event_type}]"))

with client:
    import time
    time.sleep(300)  # listen for 5 minutes

Async mode:

import asyncio
from nixwrap.stats import StatsClient

async def main():
    client = StatsClient()
    client.start()
    async for event in client.events():
        print(event.event_type)
        if event.event_type == "GoalScored":
            print(f"  {event.scorer.name} scored!")

asyncio.run(main())

5. Tracker API (Player Ranks)

from nixwrap.tracker import TrackerClient

client = TrackerClient()  # random browser fingerprint per request
stats = client.fetch("Steam|123456789|0", "PlayerName")

if stats.error:
    print(f"Error: {stats.error}")
else:
    print(f"Last updated: {stats.last_updated}")
    print(f"Lifetime: {stats.lifetime.wins} wins, {stats.lifetime.goals} goals")
    for pid, rank in stats.ranks.items():
        print(f"  {rank.playlist_name}: {rank.tier_name} {rank.division_name} "
              f"({rank.mmr} MMR, #{rank.rank_percentile}%)")
        if rank.win_streak:
            direction = "^" if rank.win_streak_type == "win" else "v"
            print(f"    Streak: {direction}{rank.win_streak}")

Results are cached for 5 minutes (tracker.gg update interval).

6. GUI / Overlay

from PySide6.QtWidgets import QApplication
from nixwrap.gui import (
    create_overlay, WindowConfig, WindowType,
    Painter, Color, THEME_DARK, FadeAnimation,
)

class MyOverlay:
    def __init__(self):
        self.win = create_overlay(600, 200, corner_radius=12, opacity=0.95)
        self.win._paint = self._paint
        self.win.snap_to_bottom_center(margin=20)

    def _paint(self, painter_q):
        p = Painter(painter_q)
        p.fill_rect(0, 0, 600, 200,
                     THEME_DARK.background.with_alpha(216), radius=12)
        p.stroke_rect(0, 0, 599, 199,
                       THEME_DARK.divider, width=1, radius=12)
        p.draw_text("Hello Rocket League!", 20, 40,
                     color=THEME_DARK.text_primary)

app = QApplication([])
overlay = MyOverlay()
app.exec()

Optional Dependencies

Extra Packages What you get
[tracker] curl-cffi better tracker.gg support
[gui] PySide6 Overlay windows, painter, colors, fonts, animations
[input] dualsense-controller, keyboard, bundled hidapi.dll Xbox (XInput), PS5 DualSense, keyboard hotkey detection
[all] all of the above Everything

Requirements

  • Python >= 3.10
  • pycryptodome >= 3.18 (save file AES)
  • psutil >= 5.9 (process detection)

Acknowledgements

Contributing

Do you want to make this library even better? Contributions are highly encouraged and appreciated.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nixwrap_rl-0.1.0.tar.gz (143.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nixwrap_rl-0.1.0-py3-none-any.whl (151.7 kB view details)

Uploaded Python 3

File details

Details for the file nixwrap_rl-0.1.0.tar.gz.

File metadata

  • Download URL: nixwrap_rl-0.1.0.tar.gz
  • Upload date:
  • Size: 143.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for nixwrap_rl-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7632fd327605cab63d7b84fe1b9b0c411a52e88844c65b74240135e7f6a98a50
MD5 6692e2de6eee1edacb8dcd6ea2eeea8c
BLAKE2b-256 fa71d5d20aeda2cc66421052e22d7e10cf7bdeba002aa39e5e93a22cf2fb392c

See more details on using hashes here.

File details

Details for the file nixwrap_rl-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: nixwrap_rl-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 151.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for nixwrap_rl-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f4087a877930a8a4e67142a81197acddeb9d84fe075fd6892eb4a5fa0abc8990
MD5 37bae9feffe6446cbff5f38a11ae6e9f
BLAKE2b-256 109ab4002c6805a4ccf6401372662b52653a72affdb64dc13d01775dd0475c80

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page