Match Schema
What is it?
A match configuration file contains everything that Get5 and your server needs to host a series. This includes locking players to their correct team and side, setting the map(s) and configuring the game rules.
Two files ship with Get5 that give a general idea of what can be included in a match config. A Valve KeyValue
format can be found here, and a JSON
format can be found here. In this
documentation, we'll go through what each value means, but do note that only the values team1
, team2
and
maplist
are required to start a match. We recommend using the JSON format whenever possible, as JSON has way
better support in various programming languages than Valve's KeyValue format (which essentially has none).
The schema
type SteamID = string //
type Get5PlayerSet = { [key: SteamID]: string } | SteamID[] //
interface Get5MatchTeam {
"id": string | undefined //
"players": Get5PlayerSet //
"coaches": Get5PlayerSet | undefined //
"name": string | undefined //
"tag": string | undefined //
"flag": string | undefined //
"logo": string | undefined //
"series_score": number | undefined //
"matchtext": string | undefined //
"fromfile": string | undefined //
}
interface Get5MapListFromFile {
"fromfile": string //
}
interface Get5Match {
"match_title": string | undefined //
"matchid": string | undefined //
"clinch_series": boolean | undefined //
"num_maps": number | undefined //
"scrim": boolean | undefined //
"wingman": boolean | undefined //
"players_per_team": number | undefined //
"coaches_per_team": number | undefined //
"coaches_must_ready": boolean | undefined //
"min_players_to_ready": number | undefined //
"min_spectators_to_ready": number | undefined //
"skip_veto": boolean | undefined //
"veto_first": "team1" | "team2" | "random" | undefined //
"veto_mode": ['team1_ban' | 'team2_ban'
| 'team1_pick' | 'team2_pick'] | undefined //
"side_type": "standard" | "always_knife"
| "never_knife" | "random" | undefined //
"map_sides": ["team1_ct" | "team1_t" | "knife"] | undefined //
"spectators": { //
"name": string | undefined //
"players": Get5PlayerSet | undefined //
"fromfile": string | undefined //
} | undefined
"maplist": string[] | Get5MapListFromFile //
"favored_percentage_team1": number | undefined //
"favored_percentage_text": string | undefined //
"team1": Get5MatchTeam //
"team2": Get5MatchTeam | undefined //
"cvars": { [key: string]: string | number } | undefined //
}
Team assignment priority
If you define a Steam ID in more than one location in your match configuration, it will be evaluated in this order to determine where to put the player:
- Spectator
- Coach for
team1
- Coach for
team2
- Player for
team1
- Player for
team2
If a player's Steam ID was not found in any of these locations, they will be removed from the server unless you are in scrim mode.
Examples
These examples are identical in the way they would work if loaded.
Example only
map_sides
would only work with skip_veto: true
.
{
"match_title": "Astralis vs. NaVi",
"matchid": "3123",
"clinch_series": true,
"num_maps": 3,
"wingman": false,
"players_per_team": 5,
"coaches_per_team": 2,
"coaches_must_ready": true,
"min_players_to_ready": 2,
"min_spectators_to_ready": 0,
"skip_veto": false,
"veto_first": "team1",
"side_type": "standard",
"spectators": {
"name": "Blast PRO 2021",
"players": {
"76561197987511774": "Anders Blume"
}
},
"maplist": [
"de_dust2",
"de_nuke",
"workshop/1193875520/de_aztec",
"de_inferno",
"de_mirage",
"de_vertigo",
"de_ancient",
"de_overpass"
],
"map_sides": [
"team1_ct",
"team2_ct",
"knife"
],
"team1": {
"fromfile": "addons/sourcemod/get5/team_navi.json"
},
"team2": {
"id": "3752",
"name": "Astralis",
"tag": "Astralis",
"flag": "DK",
"logo": "astr",
"matchtext": "Defending Champions",
"players": {
"76561197990682262": "Xyp9x",
"76561198010511021": "gla1ve",
"76561197979669175": "K0nfig",
"76561198028458803": "BlameF",
"76561198024248129": "farlig"
},
"coaches": {
"76561197987144812": "Trace"
}
},
"cvars": {
"hostname": "Get5 Match #3123",
"mp_friendlyfire": "0",
"get5_stop_command_enabled": "0",
"sm_practicemode_can_be_started": "0"
}
}
fromfile
example:
{
"id": "1348",
"name": "Natus Vincere",
"tag": "NaVi",
"flag": "UA",
"logo": "navi",
"players": {
"76561198034202275": "s1mple",
"76561198044045107": "electronic",
"76561198246607476": "b1t",
"76561198121220486": "Perfecto",
"76561198040577200": "sdy"
},
"coaches": {
"76561198013523865": "B1ad3"
}
}
And in TypeScript, using the above interface definition file:
const match_schema: Get5Match = {
"match_title": "Astralis vs. NaVi",
"matchid": "3123",
"clinch_series": true,
"num_maps": 3,
"wingman": false,
"players_per_team": 5,
"coaches_per_team": 2,
"coaches_must_ready": true,
"min_players_to_ready": 2,
"min_spectators_to_ready": 0,
"skip_veto": false,
"veto_first": "team1",
"side_type": "standard",
"spectators": {
"name": "Blast PRO 2021",
"players": {
"76561197987511774": "Anders Blume"
}
},
"maplist": [
"de_dust2",
"de_nuke",
"workshop/1193875520/de_aztec",
"de_inferno",
"de_mirage",
"de_vertigo",
"de_ancient",
"de_overpass"
],
"map_sides": ["team1_ct", "team2_ct", "knife"], // Example; would only work with "skip_veto": true
"team1": {
"fromfile": "addons/sourcemod/get5/team_navi.json"
},
"team2": {
"id": "3752",
"name": "Astralis",
"tag": "Astralis",
"flag": "DK",
"logo": "astr",
"matchtext": "Defending Champions",
"players": {
"76561197990682262": "Xyp9x",
"76561198010511021": "gla1ve",
"76561197979669175": "K0nfig",
"76561198028458803": "BlameF",
"76561198024248129": "farlig"
},
"coaches": {
"76561197987144812": "Trace"
}
},
"cvars": {
"hostname": "Get5 Match #3123",
"mp_friendlyfire": "0",
"get5_stop_command_enabled": "0",
"sm_practicemode_can_be_started": "0"
}
}
// And the config file could be placed on the server like this:
const json = JSON.stringify(match_schema);
fs.writeFileSync('addons/sourcemod/get5/astralis_vs_navi_3123.json', json);
All strings, no brakes
Note that false
does not exist in the KeyValue format and that all numerical values are wrapped in quotes. The
empty strings as values in dictionaries (maplist
and map_sides
) are also required.
"Match"
{
"match_title" "Astralis vs. NaVi"
"matchid" "3123"
"clinch_series" "1"
"num_maps" "3"
"wingman" "0"
"players_per_team" "5"
"coaches_per_team" "2"
"coaches_must_ready" "1"
"min_players_to_ready" "2"
"min_spectators_to_ready" "0"
"skip_veto" "0"
"veto_first" "team1"
"side_type" "standard"
"spectators"
{
"name" "Blast PRO 2021"
"players"
{
"76561197987511774" "Anders Blume"
}
}
"maplist"
{
"de_dust2" ""
"de_nuke" ""
"workshop/1193875520/de_aztec" ""
"de_inferno" ""
"de_mirage" ""
"de_vertigo" ""
"de_ancient" ""
"de_overpass" ""
}
"map_sides" // Example; would only work with "skip_veto" "1"
{
"team1_ct" ""
"team2_ct" ""
"knife" ""
}
"team1"
{
"fromfile" "addons/sourcemod/get5/team_navi.cfg"
}
"team2"
{
"id" "3752"
"name" "Astralis"
"tag" "Astralis"
"flag" "DK"
"logo" "astr"
"matchtext" "Defending Champions"
"players"
{
"76561197990682262" "Xyp9x"
"76561198010511021" "gla1ve"
"76561197979669175" "K0nfig"
"76561198028458803" "BlameF"
"76561198024248129" "farlig"
}
"coaches"
{
"76561197987144812" "Trace"
}
}
"cvars"
{
"hostname" "Get5 Match #3123"
"mp_friendlyfire" "0"
"get5_stop_command_enabled" "0"
"sm_practicemode_can_be_started" "0"
}
}
fromfile
example:
"Team"
{
"id" "1348"
"name" "Natus Vincere"
"tag" "NaVi"
"flag" "UA"
"logo" "navi"
"matchtext" "Challengers"
"players"
{
"76561198034202275" "s1mple"
"76561198044045107" "electronic"
"76561198246607476" "b1t"
"76561198121220486" "Perfecto"
"76561198040577200" "sdy"
}
"coaches"
{
"76561198013523865" "B1ad3"
}
}