dota2-gsi
provides an event driven interface for Dota 2's live GameState Integration data. When configured, the Dota client will send regular messages to the dota2-gsi
server, which emits an event for each attribute whenever it changes.
npm install dota2-gsi
var d2gsi = require('dota2-gsi');
var server = new d2gsi([options]);
The server can be configured by passing an optional object to the constructor:
{
port: The port that the server should listen on (default: 3000),
ip: The IP address that the server should listen on (default: "0.0.0.0"),
tokens: A single string or array of strings that are valid auth tokens (default: no auth required)
}
The server has one member
server.events - An EventEmitter used to notify when new clients connect
Using events
var d2gsi = require('dota2-gsi');
var server = new d2gsi();
server.events.on('newclient', function(client) {
console.log("New client connection, IP address: " + client.ip);
if (client.auth && client.auth.token) {
console.log("Auth token: " + client.auth.token);
} else {
console.log("No Auth token");
}
client.on('player:activity', function(activity) {
if (activity == 'playing') console.log("Game started!");
});
client.on('hero:level', function(level) {
console.log("Now level " + level);
});
client.on('abilities:ability0:can_cast', function(can_cast) {
if (can_cast) console.log("Ability0 off cooldown!");
});
});
Polling the gamestate manually. There is no guarantee that all of the objects in the gamestate exist, so be sure to null check or use a try/catch when polling.
var d2gsi = require('dota2-gsi');
var server = new d2gsi();
var clients = [];
server.events.on('newclient', function(client) {
console.log("New client connection, IP address: " + client.ip);
if (client.auth && client.auth.token) {
console.log("Auth token: " + client.auth.token);
} else {
console.log("No Auth token");
}
clients.push(client);
});
setInterval(function() {
clients.forEach(function(client, index) {
if (client.gamestate.hero && client.gamestate.hero.level) {
console.log("Client " + index + " is level " + client.gamestate.hero.level);
}
});
}, 10 * 1000); // Every ten seconds
Identifying different clients using unique auth tokens. With the changes that allow observers/spectators to receive all data this usually isn't necessary any longer, unless you want to allow multiple spectators to join the server for redundancy.
var d2gsi = require('dota2-gsi');
var server = new d2gsi({
port: 9001,
tokens: [
"6hCG4n_team1_player1",
"6hCG4n_team1_player2",
"6hCG4n_team1_player3",
"6hCG4n_team1_player4",
"6hCG4n_team1_player5"
]
});
server.events.on('newclient', function(client) {
if (client.auth && client.auth.token == "6hCG4n_team1_player1") {
console.log("Client 1:1 connected");
client.on('hero:name', function(hero_name) {
set_LAN_booth_display(1, 1, hero_name); // Set the displays on the TI booths for example
});
}
});
The server events
member emits the newclient
event whenever a new client connects (based on IP address), returning the new client object. Each client has three members:
client.ip - IP address of the client
client.auth.token - Auth token used by the client (auth or auth.token may be null)
client.gamestate - The latest gamestate received from the client
Clients will emit the following events any time they change. This list may not be complete, as Valve can silently change the key names or add news ones at any time. If you discover some new outputs, please send a pull request!
All team#
references may either be team2
for Radiant, or team3
for Dire. All player#
references range from player0
to player9
, where 0-4 are the Radiant team and 5-9 are the Dire.
newdata - The entire raw json object sent from the Dota client
The gamestate object mirrors this structure. For example
client.gamestate.abilities.team2.player0.ability1.can_cast
client.gamestate.buildings.dire.dota_badguys_fort.health
Child members in the gamestate object may be null, so use try/catch
statements when querying it.
provider
, map
, and some of player
. If you're trying to initialise values such as map:daytime
, the easiest way to achieve it is to wait on the first map:gametime
event then manually query the values from the gamestate.To configure the Dota client to report gamestate, you need to add a config file in steamapps\common\dota 2 beta\game\dota\cfg\gamestate_integration\
. The file must use the name pattern called gamestate_integration_*.cfg
, for example gamestate_integration_dota2-gsi.cfg
.
The following example is included in this repository, you can copy it straight into your Dota directory to get started.
"dota2-gsi Configuration"
{
"uri" "http://localhost:3000/"
"timeout" "5.0"
"buffer" "0.1"
"throttle" "0.1"
"heartbeat" "30.0"
"data"
{
"buildings" "1"
"provider" "1"
"map" "1"
"player" "1"
"hero" "1"
"abilities" "1"
"items" "1"
"draft" "1"
"wearables" "1"
}
"auth"
{
"token" "hello1234"
}
}
For more information, see the CS:GO GameState Integration page
Full player data is now available, but only to spectators and observers (as one would expect). The existing single player GSI data is still available, however the names of events are different to what is listed above. Please refer to previous versions of this readme or query uncomment to console logging in index.js to see which keys are available
Shoutout to /u/antonpup for his C# Gamestate Integration server and inadvertently letting me know this existed.