Repository navigation
Stream events
ProLeak can send its events and log lines to programs outside the game: an OBS overlay, a
Twitch bot, a script. The stream is a WebSocket on 127.0.0.1. It is off until you turn it on,
and a slow client never slows the game.
Contents
In the game, Mods > Advanced > Turn on the stream. The setting is saved, so the stream starts
with the game from then on. In ProLeak/config/proleak.yml:
stream: true # listen when the game starts
stream_port: 47600 # on 127.0.0.1
stream_origins: ["null"] # browser pages allowed to connect (see Access)While the stream listens, ProLeak keeps ProLeak/data/stream.json:
{"port": 47600, "token": "3f9a0c..."}The file is removed when the stream stops. The token is made the first time the stream starts
and kept, as stream_token in proleak.yml, until you press New token in Mods > Advanced.
A new token disconnects every client that used the old one; clients connect again with the
new token from stream.json.
- Every client sends the token in the address:
ws://127.0.0.1:47600/?token=<token>. A missing or wrong token is refused with HTTP 403. - A browser adds an
Originheader naming the page that connects. Only the origins listed instream_originsget in; a page loaded from a local file (an OBS browser source pointing at a file) has the originnull. Programs that send noOrigin, such as the Python client, need only the token. Every local file and every sandboxed frame on any website has the originnulltoo, so oncenullis listed only the token keeps other pages out. - At most 8 clients connect at once.
- Anyone who can read the game folder can read
stream.json, and with it the stream (events only: the stream takes no commands).
Every message is a JSON text frame. On connecting, the server says hello and lists the events a client can ask for:
{"type": "hello", "protocol": 1, "proleak": "0.1.0", "events": ["chat.received", "unit.built", "..."]}Nothing more arrives until the client subscribes. A subscription replaces the previous one:
{"type": "subscribe", "events": ["wave.*", "unit.built"], "log": true}In a pattern, * stands for one or more whole name parts: wave.* takes wave.started and
wave.ended. The game events can be streamed; raw network events (net.*)
cannot.
Then the server sends:
type |
Fields |
|---|---|
event |
name, phase (pre or post), cancelled, frame, time (UTC), fields (as the events reference lists them; units and players by id) |
log |
time, level, source (a plugin id, or core), message
|
dropped |
count: messages this client missed since the last report |
error |
message: why a request was refused. After a refused subscription the connection stays open; after a malformed frame (binary, fragmented, or larger than 64 KB) it closes |
Each event arrives once for its post phase, and also for its pre phase when a plugin handles that phase. A subscription takes at most 64 patterns.
A client that reads slowly loses messages rather than holding the game back, and gets a
dropped message before the next one it receives. A client that accepts no data for 10 s is
disconnected.
This overlay is an HTML file shown by an OBS browser source. Its URL carries the token,
file:///path/overlay.html?token=<token>, copied once from stream.json (again after a
New token), and stream_origins lists "null":
<!doctype html>
<meta charset="utf-8">
<body style="color: white; font: 24px sans-serif">
<div id="wave"></div>
<script>
const token = new URLSearchParams(location.search).get("token");
const ws = new WebSocket(`ws://127.0.0.1:47600/?token=${token}`);
ws.onopen = () => ws.send(JSON.stringify({type: "subscribe", events: ["wave.started"]}));
ws.onmessage = (m) => {
const msg = JSON.parse(m.data);
if (msg.type === "event") {
document.getElementById("wave").textContent = `Wave ${msg.fields.wave}`;
}
};
</script>proleak-client reads stream.json itself:
import asyncio
import proleak_client
async def main():
async with proleak_client.connect() as client:
await client.subscribe(["unit.built"])
async for message in client:
print(message["name"], message["fields"])
asyncio.run(main())Using ProLeak
Features
Tutorial
- Your first plugin
- Plugin basics
- Handling events
- Plugin settings
- User interface
- Players, units and game data
- Purchases, signals and pings
- Chat, camera, input and more
- Game assets
- Game modes
- Game updates
- Publishing plugins
Reference