=========
py-slippi
=========

Py-slippi is a Python parser for `.slp <https://github.com/project-slippi/slippi-wiki/blob/master/SPEC.md>`_ game replay files for `Super Smash Brothers Melee <https://en.wikipedia.org/wiki/Super_Smash_Bros._Melee>`_ for the Nintendo GameCube. These replays are generated by Jas Laferriere's `Slippi <https://github.com/JLaferri/project-slippi>`_ recording code, which runs on a Wii or the `Dolphin <https://dolphin-emu.org/>`_ emulator.

Installation
============

*Requires Python >= 3.7*. To install, run the following command (optionally inside a `virtual environment <https://packaging.python.org/tutorials/installing-packages/#optionally-create-a-virtual-environment>`_):

    pip install py-slippi

API Docs
========

See the `Module Index <https://py-slippi.readthedocs.io/en/latest/py-modindex.html>`_ for detailed API docs, starting with `slippi.game <https://py-slippi.readthedocs.io/en/latest/source/slippi.html#module-slippi.game>`_.

Usage
=====

py-slippi supports both event-based and object-based parsing. Object-based parsing is generally easier, but event-based parsing is more efficient and supports reading partial or in-progress games.

**Object-based parsing**::

    >>> from slippi import Game
    >>> Game('test/replays/game.slp')
    Game(
        end=End(
            lras_initiator=None,
            method=Method.CONCLUSIVE),
        frames=[...](5209),
        metadata=Metadata(
            console_name=None,
            date=2018-06-22 07:52:59+00:00,
            duration=5209,
            platform=Platform.DOLPHIN,
            players=(
                Player(
                    characters={InGameCharacter.MARTH: 5209},
                    netplay_name=None),
                Player(
                    characters={InGameCharacter.FOX: 5209},
                    netplay_name=None),
                None,
                None)),
        start=Start(
            is_frozen_ps=None,
            is_pal=None,
            is_teams=False,
            players=(
                Player(
                    character=CSSCharacter.MARTH,
                    costume=3,
                    stocks=4,
                    tag=,
                    team=None,
                    type=Type.HUMAN,
                    ucf=UCF(
                        dash_back=DashBack.OFF,
                        shield_drop=ShieldDrop.OFF)),
                Player(
                    character=CSSCharacter.FOX,
                    costume=0,
                    stocks=4,
                    tag=,
                    team=None,
                    type=Type.CPU,
                    ucf=UCF(
                        dash_back=DashBack.OFF,
                        shield_drop=ShieldDrop.OFF)),
                None,
                None),
            random_seed=3803194226,
            slippi=Slippi(
                version=1.0.0),
            stage=Stage.YOSHIS_STORY))

Frame data is elided when you print games, but you can inspect a sample frame with e.g. :code:`game.frames[0]`.

**Event-driven API**::

    >>> from slippi.parse import parse
    >>> from slippi.parse import ParseEvent
    >>> handlers = {ParseEvent.METADATA: print}
    >>> parse('test/replays/game.slp', handlers)
    Metadata(
        console_name=None,
        date=2018-06-22 07:52:59+00:00,
        duration=5209,
        platform=Platform.DOLPHIN,
        players=(
            Player(
                characters={InGameCharacter.MARTH: 5209},
                netplay_name=None),
            Player(
                characters={InGameCharacter.FOX: 5209},
                netplay_name=None),
            None,
            None))

👉 You can pass a stream to :code:`parse`, such as :code:`sys.stdin.buffer`! This is useful for e.g. decompressing with :code:`gunzip`, or reading from an in-progress replay via :code:`tail -c+1 -f`.
