> For the complete documentation index, see [llms.txt](https://walksy.gitbook.io/walksylib-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://walksy.gitbook.io/walksylib-docs/advanced/teams.md).

# Teams

Teams are groups of players that the **user** defines once and **every WalksyLib mod** can use.

## How teams work

WalksyLib owns the teams. Each team has:

* a **name**, such as "Team 1"
* a list of **members**, which are player names

Users manage teams on WalksyLib's own **Teams** page, which is part of the WalksyLib section of the config screen. They create, rename and delete teams, and add members by picking from online players or typing any username.

This allows your mod to:

1. **Adds per-team settings.** Your config gets a "Teams" page list with one page per team, holding your options for that team.
2. **Looks up players.** At runtime you ask which team a player is in and use that team's settings.

Teams are saved in `config/WalksyLib/walksylib.json`&#x20;

## Adding per-team settings

### With `TeamOption`&#x20;

`TeamOption` is a setting that stores one value per team. Declare it once as a field:

```java
import main.walksy.lib.core.teams.TeamOption;

public static final TeamOption<Boolean> GLOW = TeamOption.ofBoolean("Glow", true);
public static final TeamOption<WLColor> COLOR = TeamOption.ofColor("Color", new WLColor(255, 255, 255, 255));
public static final TeamOption<Float> SCALE = TeamOption.ofNumber("Scale", 1.0f, 0.5f, 2.0f, 0.1f);
```

Then add them to your config with `Options.ofTeams(...)`:

```java
Category.builder("Teams")
    .option(Options.ofTeams(GLOW, COLOR, SCALE).build())
    .build()
```

Each team gets a page with Glow, Color and Scale. **Renames and deletions are handled for you**: when the user renames "Friends" to "Squad", the values follow it.

Available types:

| Factory                                                   | Value          |
| --------------------------------------------------------- | -------------- |
| `TeamOption.ofBoolean(name, default)`                     | `Boolean`      |
| `TeamOption.ofNumber(name, default, min, max, increment)` | any `Number`   |
| `TeamOption.ofString(name, default)`                      | `String`       |
| `TeamOption.ofColor(name, default)`                       | `WLColor`      |
| `TeamOption.ofEnum(name, default, EnumClass.class)`       | an enum        |
| `TeamOption.ofStringList(name, default)`                  | `List<String>` |
| `TeamOption.ofSelectionList(name, default, ListEntries)`  | `List<String>` |

Read a value with `get(team)`. It returns the default if the team has never been customised:

```java
boolean glow = GLOW.get("Friends");
```

### With your own options

When `TeamOption` isn't enough, for example if each team needs a texture, a preview or a whole style object, build the page yourself. You store the data, keyed by team name:

```java
private static final Map<String, TeamStyle> STYLES = new HashMap<>();

private static TeamStyle style(String team) {
    return STYLES.computeIfAbsent(team, name -> new TeamStyle());
}
```

```java
Options.ofTeams(team -> List.of(
        Options.ofColor("Color", () -> style(team).color, DEFAULT_COLOR, value -> style(team).color = value).build(),
        Options.ofCroppedTexture("Badge", () -> style(team).badge, CroppedTexture.NONE, value -> style(team).badge = value).build()))
    .onRenamed((from, to) -> STYLES.put(to, STYLES.remove(from)))
    .onRemoved(STYLES::remove)
    .build();
```

To split each team's page into collapsible groups, use `Options.ofTeamGroups(team -> List<OptionGroup>)` instead.

{% hint style="warning" %}
When you build pages yourself, **you** must handle `onRenamed` and `onRemoved`. Without them, a renamed team loses its settings and a deleted team leaves stale data behind. `TeamOption` does this for you.
{% endhint %}

## Looking up a player's team

```java
import main.walksy.lib.core.WalksyLib;

String team = WalksyLib.getInstance().getGlobalTeams().teamOf(player.getName().getString());
```

`teamOf` returns the team name, or `null` if the player isn't in any team. Matching ignores case and surrounding spaces. If a player is in more than one team, the first team in the user's list wins.

Here's an example:

```java
private static WLColor colorFor(Player player) {
    String team = WalksyLib.getInstance().getGlobalTeams().teamOf(player.getName().getString());
    if (team == null || !GLOW.get(team)) {
        return null;
    }
    return COLOR.get(team);
}
```

## Other `GlobalTeams` methods

| Method           | Returns                              |
| ---------------- | ------------------------------------ |
| `names()`        | Every team name, in the user's order |
| `members(team)`  | The player names in a team           |
| `teamOf(player)` | The player's team, or `null`         |

Treat these as **read-only**. Teams are the user's to manage, from the Teams page.

## Example: CustomHitboxes

CustomHitboxes gives each team a full hitbox style with grouped options and a live preview:

```java
Category.builder("Teams")
    .option(Options.ofTeamGroups(team -> {
            final HitboxStyle style = HitboxStyles.team(team);
            return style.groups(HitboxPreview.of(style, () -> HitboxStyles.typeOf(PLAYER_ID)));
        })
        .onRenamed(HitboxStyles::renameTeam)
        .onRemoved(HitboxStyles::removeTeam)
        .build())
    .build();
```

When rendering, it checks teams before its per-entity settings:

```java
final String team = WalksyLib.getInstance().getGlobalTeams().teamOf(player.getName().getString());
final HitboxStyle style = team == null ? null : TEAMS.get(team);
```
