Skip to content

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

TypeScript interface definition of a match configuration
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:

  1. Spectator
  2. Coach for team1
  3. Coach for team2
  4. Player for team1
  5. 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.

addons/sourcemod/get5/astralis_vs_navi_3123.json
{
  "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:
addons/sourcemod/get5/team_navi.json
{
  "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:

Typescript JSON example with Node.js
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.

addons/sourcemod/get5/astralis_vs_navi_3123.cfg
"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:
addons/sourcemod/get5/team_navi.cfg
"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"
    }
}