Custom rosters

The roster pack

One file, one league at one moment. Here's every field the game reads, and what it does with each.

A roster pack is a JSON file called roster-pack.json. Here's one cut down to a team and two players. The example repository has complete ones.

{
  "format": "bladeybiscuit.rosters",
  "formatVersion": 1,
  "league": "POND",
  "season": "2026-27",
  "snapshot": "2026-10-05",
  "teams": [
    {
      "id": "PIN", "name": "Pinecrest Porcupines", "city": "Pinecrest",
      "colors": { "primary": "#1E4D2B", "secondary": "#F2E3C6" },
      "lines": {
        "forwards": [[102, 101, 103], [105, 104, 106], [208, 107, 108]],
        "defense": [[113, 114], [115, 116], [117, 118]],
        "goalies": [119, 120]
      }
    }
  ],
  "players": [
    {
      "id": 101, "firstName": "Owen", "lastName": "Thistlewood", "team": "PIN", "number": 19,
      "position": "C", "handedness": "L", "heightCm": 185, "weightKg": 86,
      "ratings": { "overall": 82, "speed": 79, "passing": 91, "stickhandling": 96, "hockeySense": 88 }
    },
    {
      "id": 119, "firstName": "Ansel", "lastName": "Fjordby", "team": "PIN", "number": 31,
      "position": "G", "handedness": "L", "heightCm": 193, "weightKg": 91,
      "ratings": { "overall": 75, "reflexes": 78, "positioning": 74, "reboundControl": 70 }
    }
  ]
}

Leave a field out and the game uses its default. You can add fields of your own, like notes to yourself or birthdays. The game ignores anything it doesn't know.

The league

The fields at the top describe the whole pack.

Field What it does
format Required Always "bladeybiscuit.rosters". It's how the game knows it's a roster pack.
formatVersion 1. If a newer version of the game ever changes the format, it'll use a bigger number. This version refuses a pack numbered higher than it knows, and asks for an update.
league A few capital letters for the league. Team select shows them over each team (default "League").
season The season, like "2026-27". It appears next to the date in the Rosters menu.
snapshot The day the rosters are as of, yyyy-MM-dd. Just for your records: the date people see comes from roster-set.json.
teams Required The teams. A league needs at least two.
players Required Every player on every team, in one list. Each one says which team they're on.
files Every picture the pack uses (its logos), with their checksums: see Logos and art.

Teams

Field What it does
id Required The team's short name, like "PIN": 2 to 4 capital letters. It's what the scoreboard shows, and players join a team by it. A longer one is cut to 4 letters.
name The full name, as team select shows it (default "Team").
city Where they're from.
colors primary and secondary, as "#rrggbb" colour codes.
logo A picture of the team's logo, beside the pack: see Logos and art.
lines The depth chart: lines, pairs and goalies.
nickname, conference, division Kept with the team, not shown yet.

Colours

primary is the jersey colour and secondary is the trim. The game makes the rest from those two:

  • Home jerseys are the primary colour, with the trim, names and numbers in the secondary. If the primary is light (a yellow, say), the two swap: the jersey takes the dark colour and the light one trims it.
  • Away jerseys are white, trimmed in the team's colour.
  • Pants are a dark shade of the primary. Helmets are dark with the home jersey and light with the away one.
  • The design (stripes, yokes, sleeve bands) is picked from the team's name. Rename a team and its design changes with it.

Write each colour as # and six hex digits: #1E4D2B is a dark green. Any colour picker gives you these, including the ones in Google search and in most paint programs. A team without colours plays in navy (#334066) and white.

Lines

The game dresses three forward lines, three defence pairs and a goalie, and rolls them through the game itself, line changes and all. lines says who plays where. Each player is listed by their id.

"lines": {
  "forwards": [[102, 101, 103], [105, 104, 106], [208, 107, 108], [111, 110, 112]],
  "defense": [[113, 114], [115, 116], [117, 118]],
  "goalies": [119, 120]
}
Field What it holds
forwards Forward lines, best first. Each is [left wing, center, right wing].
defense Defence pairs, best first. Each is [left D, right D].
goalies Goalies, the starter first.
  • The spot decides the position. A player plays wherever their line puts them, whatever their own position says. That's how you move a center to the wing.
  • Only the first three lines and pairs dress. Players on a fourth line, a fourth pair or not on any line are the team's spares. The game uses them to fill holes.
  • The first goalie found plays. The rest are backups.
  • A hole is fine: null in a spot ([102, null, 103]) leaves it empty for the game to fill.
  • One spot per player. If someone's listed twice, the second spot is treated as a hole.
  • powerPlay and penaltyKill lists are allowed, but the game picks its own special teams.

When a lineup's short

The game never refuses a team for being short. It fills each empty spot with the best spare by overall, keeping forwards to forward spots and defencemen to defence spots if it can, then any skater. If nobody's left, it calls up an average player called “Call-up”. A team with no goalie in goalies gets the first player listed with "position": "G", or a call-up.

The game fills spots in order (first line, first pair, second line…), and a spare can be someone listed further down. Their own spot is then a hole too, so one gap can shuffle a whole line. The checker shows each lineup as the game will dress it. After installing a pack, the game says how many teams it had to fill out.

No lines at all

You can leave lines out completely. The game dresses each team itself: forwards fill center, left wing, right wing on each line in turn, and defencemen fill each pair, left then right. The highest overall goes first, so with no ratings at all it's the order they're listed in. The smallest pack works this way.

Players

Field What it does
id Required A whole number that's this player's alone in the pack, and stays theirs in every update. Lines refer to players by it. Any numbers you like: 1, 2, 3 is fine. See Keep each player's id.
team Required The id of their team, exactly ("PIN", not "pin").
firstName, lastName Their name. The back of the jersey shows the last name in capitals.
number Their jersey number, 0 to 99.
position "C", "LW", "RW", "D" or "G". G marks a goalie. Otherwise, only forward or defenceman matters, when the game fills holes.
handedness "L" or "R": which way they shoot. For a goalie, the hand that catches. Default "L".
heightCm Height in centimetres (default 185).
weightKg Weight in kilograms (default 90).
ratings Their abilities, 0 to 99: see Ratings.

Keep each player's id

A player's id is who they are from one update to the next, so keep it the same in every update you publish, whatever else changes: their team after a trade, their number, their ratings, even their name.

  • A new player gets a new id, one nobody in your set has had before.
  • Never hand a player's id to someone else, even after they've left or retired.

The game matches players across updates by it: a season in progress takes your update's trades and rating changes for the players it already has (with season mode, coming). A player whose id changed looks like someone new, and one who took an old id looks like the player who had it.

Names

The game joins firstName and lastName with a space. On the jersey's back it uses the last name, in capitals. Particles stay with it, so "van der Berg" prints VAN DER BERG. A nickname in quotes, like "firstName": "Hal \"Tank\"", shows in menus but stays off the jersey. Accents are fine: "Mäkelä", "Lindström".

Size

Height and weight do more than set how big a player looks:

  • Bigger bodies take up more room, hit harder and are harder to knock off the puck.
  • Taller players reach a little further with the stick.
  • Taller goalies cover more of the net.

The effect on play levels off at about 170–203 cm and 70–117 kg. A height under 100 is ignored, so write 185, not 1.85.

Writing JSON by hand

JSON is strict, and the game reads it strictly:

  • Double quotes around every name and text: "name": "Pinecrest", never 'Pinecrest'.
  • No comma after the last item in a list or object.
  • No comments. To leave yourself a note, add a field: "note": "fix the third line".
  • Numbers without quotes. "number": 19 is a number. "number": "19" is text, and the game ignores it.
  • Save as UTF-8, which every modern editor does by default.

A misspelt field name doesn't stop anything. The game just doesn't see it, so "shotPowr": 90 leaves that player's shot power at 50. The checker points out names it doesn't know.