gogsi

package module
v0.0.0-...-7e9a24a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2016 License: MIT Imports: 7 Imported by: 0

README

gogsi Build Status GoDoc Go report

go get github.com/mammothbane/gogsi

The Dota 2 client is capable of streaming JSON-formatted updates about the game to an arbitrary HTTP endpoint. This library listens to those updates and converts them to a Go representation that you can manipulate as convenient.

Usage

A barebones example might look like this:

package main

import "github.com/mammothbane/gogsi"

func main() {
	gogsi.Listen("localhost:3000", func(s *gogsi.State) error {
		if s.Added.Map.NightstalkerNight {
			/* adjust your phillips hue light, play a scary noise, update statistics, log something, etc. */
		}
		return nil
	})
}

The notion of change in the Dota 2 GSI is represented by the State.Added and State.Previous fields, so, as might be expected, this snippet responds to the value of Map.NightstalkerNight changing to true. Further detail about Added and Previous can be found in the docs.

Config

A sample configuration is provided below, set up to send all game updates to localhost:3000. Save it (along with any desired changes) to game/dota/cfg/gamestate_integration/gamestate_integration_[integration_name].cfg in order to register your integration with the Dota 2 client.

"Dota 2 Sample Integration"
{
	"uri"		"http://localhost:3000"
	"timeout"	"5.0"
	"buffer"  	"0.1"
	"throttle"	"0.1"
	"heartbeat"	"30.0"
	"data"
	{
		"provider"		"1"
		"map"			"1"
		"player"		"1"
		"hero"			"1"
		"abilities"		"1"
		"items"			"1"
		"allplayers"	"1"
	}	
}

The first line (the name of the integration) should be unique.

uri is the URI of your server (usually on localhost).

buffer is the amount of time (in seconds) for which the client should wait once it has a delta to send, collecting together all deltas in the meantime in order to reduce traffic. A value of "0" causes every delta to be sent as soon as it is available.

throttle is the minimum amount of time (in seconds) the client waits before sending a new delta after receiving a 2XX response from the server.

heartbeat specifies the maximum amount of time the client waits before sending an update, even if no events have occurred.

data options are more or less self-explanatory ("1" indicates that the game client should send updates about the given item, "0" indicates that it shouldn't).

Additionally, an auth block can be specified as follows:

"Dota 2 Sample Integration"
{
	// ...
	"auth"
	{
		"token" "an_auth_token"
	}
}

This token will be transmitted with every request as state.Auth.Token, so it's easiest to use as a shared key and/or unique ID per client for a remote gogsi instance.

These options are also covered in more detail at the CS: GO GSI page.

Notes and caveats

GSI does not begin sending updates until the first time the player loads into a game. Normally (and according to Valve's spec and various observations), the heartbeat is intended to be respected while in the client UI (i.e. not loaded into a game). This does not occur until after a game is loaded for the first time. I have also come across instances in testing where the client did not send GSI updates until the 0:00 horn in the first game.

On another note, this is not a scripting or hacking tool. Anyone looking for an easy way to break into the game should look somewhere else. The GSI is provided by Valve, and it does not allow any input. No information about other heroes or creeps is available, and position data is similarly not accessible.

Credits

This package was inspired by antonpup's C# implementation.

Documentation

Overview

Package gogsi is a game state integration (GSI) library for the Dota 2 client. More information is available on github: https://github.com/mammothbane/gogsi/blob/master/README.md

Index

Constants

View Source
const (
	StateUndefined      DotaGameState = ""
	StateDisconnect     DotaGameState = "DOTA_GAMERULES_STATE_DISCONNECT"
	StateGameInProgress DotaGameState = "DOTA_GAMERULES_STATE_GAME_IN_PROGRESS"
	StateHeroSelection  DotaGameState = "DOTA_GAMERULES_STATE_HERO_SELECTION"
	StateInit           DotaGameState = "DOTA_GAMERULES_STATE_INIT"
	StateLast           DotaGameState = "DOTA_GAMERULES_STATE_LAST"
	StatePostGame       DotaGameState = "DOTA_GAMERULES_STATE_POST_GAME"
	StatePreGame        DotaGameState = "DOTA_GAMERULES_STATE_PRE_GAME"
	StateStrategyTime   DotaGameState = "DOTA_GAMERULES_STATE_STRATEGY_TIME"
	StateWaitForPlayers DotaGameState = "DOTA_GAMERULES_STATE_WAIT_FOR_PLAYERS"

	TeamUndefined DotaTeam = ""
	TeamNone      DotaTeam = "none"
	TeamDire      DotaTeam = "dire"
	TeamRadiant   DotaTeam = "radiant"

	ActivityUndefined PlayerActivity = ""
	ActivityMenu      PlayerActivity = "menu"
	ActivityPlaying   PlayerActivity = "playing"

	RuneNone RuneType = ""
)

Known state constants

Variables

This section is empty.

Functions

func Listen

func Listen(url string, fn func(state *State) error) error

Listen is the main entrypoint into gogsi.

Url

Can be any portion of a URL. Each of the following is valid and equivalent to all the others:

gogsi.Listen("http://localhost:3000", handler)
gogsi.Listen("localhost:3000", handler)
gogsi.Listen(":3000", handler)
gogsi.Listen("", handler)

A path can optionally follow:

gogsi.Listen(":3000/my/custom/url")

Defaults

If not present, the host is assumed to be 'localhost', the path is assumed to be "/", and the port is assumed to be 3000. The scheme is ignored and not validated— "my_scheme://localhost:3000" is equivalent to "http://localhost:3000".

Closure

fn contains the logic for whatever you want to do on each update. It's called as part of an HTTP handler, so a goroutine is spawned for each invocation. As such, heavy work within fn is not recommended, at least unless GSi is configured with a high buffer value. Dota will wait to receive a 2XX response until it times out (and it will retry if it doesn't receive a 2XX), so processing for too long could quickly deadlock your system or run you out of memory. If your closure returns an error, the server will respond to the Dota client with a 500, triggering a retry. A nil return from your closure always results in a 200 OK.

Types

type Abilities

type Abilities struct {
	AbilitySlice [6]*Ability
	*Attributes
}

Abilities represents the set of abilities belonging to a hero. A nil slot means that the hero does not have an ability for that slot (unlearned abilities are present but level 0.

func (Abilities) Ultimate

func (a Abilities) Ultimate() *Ability

Ultimate returns the ultimate skill.

func (*Abilities) UnmarshalJSON

func (a *Abilities) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Abilities. This is implemented custom because the incoming format from Valve is different from the gogsi representation.

func (Abilities) WithName

func (a Abilities) WithName(name string) *Ability

WithName checks whether an ability with the given name exists in the list. If so, it returns it. Otherwise, it returns nil.

type Ability

type Ability struct {
	Name     string        `json:"name"`
	Level    int           `json:"level"`
	Cooldown time.Duration `json:"cooldown"`
	CanCast  bool          `json:"can_cast"`
	Active   bool          `json:"ability_active"`
	Passive  bool          `json:"passive"`
	Ultimate bool          `json:"ultimate"`
}

Ability represents a Hero's ability.

func (*Ability) UnmarshalJSON

func (a *Ability) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Ability in order to handle custom time.Duration deserialization.

type Attributes

type Attributes struct {
	Level int `json:"level"`
}

Attributes is the current level to which a Hero's attributes (stats) are upgraded.

type Auth

type Auth struct {
	Token string `json:"token"`
}

Auth holds the token set in the integration's configuration file (a shared key is easiest). Mostly useful for remote listeners.

type DotaGameState

type DotaGameState string

DotaGameState is an enumeration of all possible dota game states.

type DotaTeam

type DotaTeam string

DotaTeam is the team the player is on. Unknown how this plays with custom games.

type GameStats

type GameStats struct {
	Kills          int
	Deaths         int
	Assists        int
	LastHits       int
	Denies         int
	KillStreak     int
	Team           DotaTeam
	ReliableGold   int
	UnreliableGold int
	GPM            int
	XPM            int
}

GameStats holds the information about a player's performance in a given game. Usually nil if the player is not currently in a game.

type Hero

type Hero struct {
	ID              int           `json:"id"`
	Name            string        `json:"name"`
	Level           int           `json:"level"`
	Alive           bool          `json:"alive"`
	Respawn         time.Duration `json:"respawn_seconds"`
	BuybackCost     int           `json:"buyback_cost"`
	BuybackCooldown time.Duration `json:"buyback_cooldown"`
	Health          int           `json:"health"`
	MaxHealth       int           `json:"max_health"`
	HealthPercent   int           `json:"health_percent"`
	Mana            int           `json:"mana"`
	MaxMana         int           `json:"max_mana"`
	ManaPercent     int           `json:"mana_percent"`
	Silenced        bool          `json:"silenced"`
	Stunned         bool          `json:"stunned"`
	Disarmed        bool          `json:"disarmed"`
	MagicImmune     bool          `json:"magicimmune"`
	Hexed           bool          `json:"hexed"`
	Muted           bool          `json:"muted"`
	Break           bool          `json:"break"`
	Debuffed        bool          `json:"has_debuff"`
}

Hero represents the hero being controlled by the connected client.

func (*Hero) UnmarshalJSON

func (h *Hero) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Hero in order to handle custom time.Duration deserialization.

type Item

type Item struct {
	Name         string        `json:"name"`
	ContainsRune string        `json:"contains_rune"`
	Charges      int           `json:"charges"`
	Cooldown     time.Duration `json:"cooldown"`
	CanCast      bool          `json:"can_cast"`
	Passive      bool          `json:"passive"`
}

Item represents a Dota 2 item.

func (*Item) UnmarshalJSON

func (i *Item) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Item in order to handle custom time.Duration deserialization.

type ItemName

type ItemName string

ItemName enumerates possible item names. As of now, this type simply captures the "empty" value.

type Items

type Items struct {
	Inventory [6]*Item
	Stash     [6]*Item
}

Items represents the entire set of item slots belonging to a hero. A nil entry in either array represents that the slot does not hold an item.

func (*Items) UnmarshalJSON

func (i *Items) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Items. This is implemented custom because the incoming format from Valve is different from the gogsi representation.

func (Items) WithName

func (i Items) WithName(name string) []*Item

WithName returns all items in the player's inventory and stash that match the given name.

type Map

type Map struct {
	Name                 string        `json:"name"`
	MatchID              int           `json:"matchid"`
	GameTime             time.Duration `json:"game_time"`
	ClockTime            time.Duration `json:"clock_time"`
	Day                  bool          `json:"daytime"`
	NightstalkerNight    bool          `json:"nightstalker_night"`
	GameState            DotaGameState `json:"game_state"`
	WinTeam              DotaTeam      `json:"win_team"`
	CustomGameName       string        `json:"customgamename"`
	WardPurchaseCooldown time.Duration `json:"ward_purchase_cooldown"`
}

Map carries information about the state of the Dota 2 map.

func (*Map) UnmarshalJSON

func (m *Map) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Map in order to handle custom time.Duration deserialization.

type Player

type Player struct {
	SteamID  string
	Name     string
	Activity PlayerActivity
	*GameStats
}

Player provides information about the Steam/Dota user currently logged in to the client.

func (*Player) UnmarshalJSON

func (p *Player) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Player, allowing us to segregate GameStats from metadata (SteamID, Name, Activity).

type PlayerActivity

type PlayerActivity string

PlayerActivity enumerates the different states a player might be in. This is not an exhaustive list.

type Provider

type Provider struct {
	Name      string    `json:"name"`
	AppID     int       `json:"appid"`
	Version   int       `json:"version"`
	Timestamp time.Time `json:"-"`
}

Provider holds Steam-related metadata about the app currently in use (Dota 2).

func (*Provider) UnmarshalJSON

func (p *Provider) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for Provider in order to handle custom time.Duration deserialization.

type RuneType

type RuneType string

RuneType enumerates the runes that a bottle could contain. At the moment, these values haven't been checked or enumerated.

type State

type State struct {
	*Auth      `json:"auth,omitempty"`
	*Provider  `json:"provider,omitempty"`
	*Map       `json:"map,omitempty"`
	*Player    `json:"player,omitempty"`
	*Hero      `json:"hero,omitempty"`
	*Abilities `json:"abilities,omitempty"`
	*Items     `json:"items,omitempty"`
	Previous   *State `json:"added,omitempty"`
	Added      *State `json:"added,omitempty"`
}

State contains all available information about the current state of a Dota 2 game at a given moment in time. Previous and Added are deltas since the last State (Added contains all new values, and Previous is what they were before.

func (*State) CanAffordBuyback

func (s *State) CanAffordBuyback() bool

CanAffordBuyback returns whether or not the player has enough gold to buy back. Ignores buyback timer.

func (*State) GoldAfterDeath

func (s *State) GoldAfterDeath() int

GoldAfterDeath returns the amount of gold the player would have if their hero were to die. Will not work properly in custom games.

func (*State) UnreliableGoldAfterDeath

func (s *State) UnreliableGoldAfterDeath() int

UnreliableGoldAfterDeath computes the amount of unreliable gold the player would have if their hero were to die. Will not work properly for custom games.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL