@vinceau/slp-realtime

slp-realtime

slp-realtime is magic - Nikki

npm version Build Status Coverage Status License

The brains and the brawn of Project Clippi.

This library provides an easy way to subscribe to real-time Slippi game events as they happen. Built using RxJS Observables, the power to subscribe to any and every event is in your hands.

Highlights

  • Read directly from Slippi Dolphin or a relay/console.
  • Custom combo detection with flexible filtering options.
  • Powerful RxJS Observable and Stream API.

Installation

This package relies on the rxjs and @slippi/slippi-js packages as a peer dependency and must be installed alongside this package.

With NPM

npm install @vinceau/slp-realtime rxjs @slippi/slippi-js

Usage

See working examples or check out the API docs.

For a list of all the subscribable events, click here.

Subscribing to In-Game Events

We can use this library to subscribe to in game events.

First, instantiate a DolphinConnection (or ConsoleConnection for relay/nintendont) and an RxSlpStream. Connect the connection to the stream by piping messages to stream.process():

const { DolphinConnection } = require("@slippi/slippi-js/node");
const { RxSlpStream } = require("@vinceau/slp-realtime");

const stream = new RxSlpStream();
const connection = new DolphinConnection();

// Pipe raw message data to the stream for processing
connection.on("message", (data) => {
stream.process(data);
});

// Connect to Dolphin at the specified address and port
connection
.connect("127.0.0.1", 51441)
.then(() => {
console.log("Successfully connected!");
})
.catch(console.error);

Then instantiate an instance of SlpRealTime and pass the RxSlpStream to it. We will use it to subscribe to desired events. For example:

const { SlpRealTime } = require("@vinceau/slp-realtime");

const realtime = new SlpRealTime();
// Read from the RxSlpStream object from before
realtime.setStream(stream);

realtime.game.start$.subscribe(() => {
console.log("game started");
});

realtime.stock.playerSpawn$.subscribe((stock) => {
const { playerIndex, count } = stock;
console.log(`player ${playerIndex + 1} spawned with ${count} stocks remaining`);
});

realtime.combo.end$.subscribe(() => {
console.log("wombo combooo!!");
});

Detecting Custom Combos

We can subscribe to the end of any and every combo but really what we want is to filter for specific combos.

First, instantiate a ComboFilter. For all the possible filtering options, see ComboFilterSettings.

const { ComboFilter } = require("@vinceau/slp-realtime");

const comboFilter = new ComboFilter();
comboFilter.updateSettings({
excludeCPUs: false, // combos on CPUs are okay
comboMustKill: false, // combos don't have to kill
minComboPercent: 40, // combos have to do at least 40% damage
});

ComboFilter has an isCombo() method which returns true if a given combo matches the specified criteria. We can hook it up to our live stream with the following:

realtime.combo.end$.subscribe((payload) => {
const { combo, settings } = payload;
if (comboFilter.isCombo(combo, settings)) {
console.log("Combo matched!");
}
});

Make a Custom HUD

Want to make your own HUD?

  1. Subscribe to percent and stock changes
  2. Write the data to a file
  3. Add files to OBS
  4. ???
  5. Profit!!
realtime.stock.percentChange$.subscribe((payload) => {
const player = payload.playerIndex + 1;
console.log(`player ${player} percent: ${payload.percent}`);
fs.writeFileSync(`./player${player}Percent.txt`, payload.percent.toFixed(0));
});

realtime.stock.countChange$.subscribe((payload) => {
const player = payload.playerIndex + 1;
console.log(`player ${player} stocks: ${payload.stocksRemaining}`);
fs.writeFileSync(`./player${player}Stocks.txt`, payload.stocksRemaining.toString());
});

NOTE: Please don't actually do this for real custom HUDs. Writing to files is slow and OBS takes a long time to update after file changes. If you actually want to build a custom layout for OBS you should use a browser source and send updates using websockets instead of writing data to a file.

Setup on WSL

If you're running the Node project inside Windows Subsystem for Linux and running Dolphin or a relay in Windows, setup requires a couple extra steps:

  1. Change the address passed to connection.connect() to the one listed in /etc/resolv.conf instead of localhost (see here)

  2. Add a firewall rule allowing access from WSL (see here)

Development

To build the library from source:

npm run build

To start the development server:

npm run watch

To run the tests:

npm run test

Acknowledgements

This project was made possible by:

License

This software is released under the terms of MIT license.

Linking back to this Github repo is much appreciated.