Interacting with Source Servers

Source provides the “A2S” protocol for querying game servers. This protocol is used by the Steam and in-game server browsers to list information about servers such as their name, player count and whether or not they’re password protected. valve.source.server provides a client implementation of A2S.

class valve.source.a2s.ServerQuerier(address, timeout=5.0)

Implements the A2S Source server query protocol

https://developer.valvesoftware.com/wiki/Server_queries

info()

Retreive information about the server state

This returns the response from the server which implements __getitem__ for accessing response fields. For example:

server = ServerQuerier(...)
print server.info()["server_name"]

The following fields are available on the response:

Field Description
response_type Always 0x49
server_name The name of the server
map The name of the map being ran by the server
folder The gamedir if the modification being ran by the server. E.g. tf, cstrike, csgo.
game A string identifying the game being ran by the server
app_id The numeric application ID of the game ran by the server. Note that this is the app ID of the client, not the server. For example, for Team Fortress 2 440 is returned instead of 232250 which is the ID of the server software.
player_count Number of players currently connected. See players() for caveats about the accuracy of this field.
max_players The number of player slots available. Note that player_count may exceed this value under certain circumstances. See players().
bot_count The number of AI players present
server_type A util.ServerType instance representing the type of server. E.g. Dedicated, non-dedicated or Source TV relay.
platform A util.Platform instances represneting the platform the server is running on. E.g. Windows, Linux or Mac OS X.
password_protected Whether or not a password is required to connect to the server.
vac_enabled Whether or not Valve anti-cheat (VAC) is enabled
version The version string of the server software

Currently the extra data field (EDF) is not supported.

ping()

Ping the server, returning the round-trip latency in milliseconds

The A2A_PING request is deprecated so this actually sends a A2S_INFO request and times that. The time difference between the two should be negligble.

players()

Retrive a list of all players connected to the server

The following fields are available on the response:

Field Description
response_type Always 0x44
player_count The number of players listed
players A list of player entries

The players field is a list that contains player_count number of messages.PlayerEntry instances which have the same interface as the top-level response object that is returned.

The following fields are available on each player entry:

Field Description
name The name of the player
score Player’s score at the time of the request. What this relates to is dependant on the gamemode of the server.
duration Number of seconds the player has been connected as a float

Note

Under certain circumstances, some servers may return a player list which contains empty name fields. This can lead to player_count being misleading.

Filtering out players with empty names may yield a more accurate enumeration of players:

query = ServerQuerier((..., ...))
players = []
for player in query.players()["players"]:
    if player["name"]:
        players.append(player)
player_count = len(players)
rules()

Retreive the server’s game mode configuration

This method allows you capture a subset of a server’s console variables (often referred to as ‘cvars’,) specifically those which have the FCVAR_NOTIFY flag set on them. These cvars are used to indicate game mode’s configuration, such as the gravity setting for the map or whether friendly fire is enabled or not.

The following fields are available on the response:

Field Description
response_type Always 0x56
rule_count The number of rules
rules A dictionary mapping rule names to their corresponding string value

Example

In this example we will query a server, printing out it’s name and the number of players currently conected. Then we’ll print out all the players sorted score-decesending.

import valve.source.a2s

SERVER_ADDRESS = (..., ...)

server = valve.source.a2s.ServerQuerier(SERVER_ADDRESS)
info = server.info()
players = server.players()

print "{player_count}/{max_players} {server_name}".format(**info)
for player in sorted(players["players"],
                     key=lambda p: p["score"], reverse=True):
    print "{score} {name}".format(**player)

Utilities

valve.source.util provides a handful of utility classes which are used when querying Source servers.

class valve.source.util.Platform(value)

A Source server platform identifier

This class provides utilities for representing Source server platforms as returned from a A2S_INFO request. Each platform is ultimately represented by one of the following integers:

ID Platform
76 Linux
108 Linux
109 Mac OS X
111 Mac OS X
119 Windows

Note

Starbound uses 76 instead of 108 for Linux in the old GoldSource style.

__eq__(other)

Check for equality between two platforms

If other is not a Platform instance then an attempt is made to convert it to one using same approach as __init__(). This means platforms can be compared against integers and strings. For example:

>>>Platform(108) == "linux"
True
>>>Platform(109) == 109
True
>>>Platform(119) == "w"
True

Despite the fact there are two numerical identifers for Mac (109 and 111) comparing either of them together will yield True.

>>>Platform(109) == Platform(111)
True
__init__(value)

Initialise the platform identifier

The given value will be mapped to a numeric identifier. If the value is already an integer it must then it must exist in the table above else ValueError is returned.

If value is a one character long string then it’s ordinal value as given by ord() is used. Alternately the string can be either of the following:

  • Linux
  • Mac OS X
  • Windows
__weakref__

list of weak references to the object (if defined)

os_name

Convenience mapping to names returned by os.name

class valve.source.util.ServerType(value)

A Source server platform identifier

This class provides utilities for representing Source server types as returned from a A2S_INFO request. Each server type is ultimately represented by one of the following integers:

ID Server type
68 Dedicated
100 Dedicated
108 Non-dedicated
112 SourceTV

Note

Starbound uses 68 instead of 100 for a dedicated server in the old GoldSource style.

__eq__(other)

Check for equality between two server types

If other is not a ServerType instance then an attempt is made to convert it to one using same approach as __init__(). This means server types can be compared against integers and strings. For example:

>>>Server(100) == "dedicated"
True
>>>Platform(108) == 108
True
>>>Platform(112) == "p"
True
__init__(value)

Initialise the server type identifier

The given value will be mapped to a numeric identifier. If the value is already an integer it must then it must exist in the table above else ValueError is returned.

If value is a one character long string then it’s ordinal value as given by ord() is used. Alternately the string can be either of the following:

  • Dedicated
  • Non-Dedicated
  • SourceTV
__weakref__

list of weak references to the object (if defined)