> ## Documentation Index
> Fetch the complete documentation index at: https://simplecloud.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Groups API

> Server-Gruppen programmatisch verwalten

Die Groups API ermöglicht das Erstellen, Abfragen, Aktualisieren und Löschen von Server-Gruppen. Zugriff über `api.group()`.

## Gruppen abrufen

```java theme={null}
// Alle Gruppen abrufen
api.group().getAllGroups()
    .thenAccept(groups -> groups.forEach(g -> System.out.println(g.getName())));

// Gruppen mit Filtern abrufen
GroupQuery query = GroupQuery.create()
    .filterByName("lobby")
    .filterByType(GroupServerType.SERVER);

api.group().getAllGroups(query)
    .thenAccept(groups -> groups.forEach(group ->
        System.out.println(group.getServerGroupId())));

// Gruppe nach Namen
api.group().getGroupByName("lobby")
    .thenAccept(group -> System.out.println(group.getServerGroupId()));

// Gruppe nach ID
api.group().getGroupById("group-uuid")
    .thenAccept(group -> System.out.println(group.getName()));
```

## Gruppe erstellen

```java theme={null}
CreateGroupRequest request = CreateGroupRequest.builder()
    .name("bedwars")
    .type(GroupServerType.SERVER)
    .minMemory(512)
    .maxMemory(1024)
    .maxPlayers(16)
    .minOnlineCount(1)
    .maxOnlineCount(10)
    .build();

api.group().createGroup(request)
    .thenAccept(group -> System.out.println("Erstellt: " + group.getServerGroupId()));
```

## Gruppe aktualisieren

```java theme={null}
UpdateGroupRequest update = UpdateGroupRequest.builder()
    .maxPlayers(32)
    .maxOnlineCount(20)
    .build();

api.group().updateGroup("group-uuid", update)
    .thenAccept(group -> System.out.println("Aktualisiert: " + group.getName()));
```

## Gruppe löschen

```java theme={null}
api.group().deleteGroup("group-uuid")
    .thenRun(() -> System.out.println("Gelöscht: group-uuid"));
```

<Warning>
  Das Löschen einer Gruppe stoppt laufende Server nicht. Stoppe Server zuerst wenn nötig.
</Warning>

## Gruppen-Properties

Gruppen unterstützen eigene Key-Value-Properties für Metadaten:

```java theme={null}
// Properties hinzufügen oder aktualisieren (merged mit bestehenden)
Map<String, Object> props = Map.of(
    "gameMode", "ADVENTURE",
    "region", "eu-west"
);
api.group().updateGroupProperties("group-uuid", props);

// Bestimmte Properties entfernen
api.group().deleteGroupProperties("group-uuid", List.of("region"));
```

Properties sind in Servern als Umgebungsvariablen mit `SIMPLECLOUD_` Präfix verfügbar.

## Group Model

<ResponseField name="serverGroupId" type="string" required>
  Eindeutige Server-Gruppen-ID.
</ResponseField>

<ResponseField name="name" type="string" required>
  Gruppenname.
</ResponseField>

<ResponseField name="type" type="GroupServerType" required>
  Gruppentyp. Nutze `SERVER` für Spielserver oder `PROXY` für Proxy-Server.
</ResponseField>

<ResponseField name="minMemory" type="integer" required>
  Minimaler Speicher in MB.
</ResponseField>

<ResponseField name="maxMemory" type="integer" required>
  Maximaler Speicher in MB.
</ResponseField>

<ResponseField name="maxPlayers" type="integer" required>
  Spielerlimit pro Server.
</ResponseField>

<ResponseField name="minOnlineCount" type="integer" required>
  Minimale Anzahl laufender Server.
</ResponseField>

<ResponseField name="maxOnlineCount" type="integer" required>
  Maximale Anzahl erlaubter Server.
</ResponseField>

<ResponseField name="properties" type="object" required>
  Eigene Metadaten, die Server der Gruppe übernehmen.
</ResponseField>

<ResponseField name="scalingConfig" type="ScalingConfig" required>
  Auto-Scaling-Einstellungen.
</ResponseField>

<ResponseField name="deploymentConfig" type="DeploymentConfig" required>
  Host-Deployment-Einstellungen.
</ResponseField>

<ResponseField name="sourceConfig" type="SourceConfig" required>
  Blueprint- oder Image-Quelle, aus der Server erstellt werden.
</ResponseField>

## ScalingConfig

<ResponseField name="min_servers" type="integer" required>
  Minimale Anzahl laufender Server.
</ResponseField>

<ResponseField name="max_servers" type="integer" required>
  Maximale Anzahl erlaubter Server.
</ResponseField>

<ResponseField name="scaling_mode" type="ScalingMode" required>
  Scaling-Strategie. Nutze `SLOTS` für freie Spielerplätze oder `SERVERS` für serverbasierte Skalierung.
</ResponseField>

<ResponseField name="available_slots" type="integer">
  Freie Slots, die bei `SLOTS`-Scaling verfügbar bleiben sollen.
</ResponseField>

<ResponseField name="player_threshold" type="number">
  Scale-up-Schwelle zwischen `0` und `1`.
</ResponseField>

<ResponseField name="scale_down" type="ScaleDownConfig" required>
  Einstellungen für das Herunterskalieren.
</ResponseField>

## Server-Start-Warteschlange

Gruppen mit dem Skalierungsmodus `SERVERS` unterstützen eine manuelle Start-Warteschlange. Anstatt einen Server sofort zu starten, kannst du eine Start-Anfrage in die Warteschlange einreihen, die der Reconciler beim nächsten Tick verarbeitet. Dies ist nützlich, wenn du genau kontrollieren möchtest, wann neue Server erstellt werden, während das `max_servers`-Limit der Gruppe eingehalten wird.

<Info>
  Die Start-Warteschlange ist nur für Gruppen mit dem Skalierungsmodus `SERVERS` verfügbar. Gruppen mit dem Modus `SLOTS` unterstützen keine Warteschlangen-Starts.
</Info>

### Server-Start einreihen

Du kannst einen Start über die Gruppen-ID einreihen oder zuerst die Gruppe per Name auflösen:

```java theme={null}
// Start nach Gruppen-ID einreihen
api.group().requestServerStart("group-uuid")
    .thenRun(() -> System.out.println("Start-Anfrage angenommen"));

// Start nach Gruppenname einreihen
api.group().getGroupByName("lobby")
    .thenCompose(group -> {
        if (group == null) {
            return CompletableFuture.failedFuture(
                new IllegalArgumentException("Gruppe nicht gefunden: lobby"));
        }
        return api.group().requestServerStart(group);
    })
    .thenRun(() -> System.out.println("Start-Anfrage für lobby angenommen"));
```

Der Reconciler verarbeitet eingereihte Starts beim nächsten Reconciliation-Tick und versucht, einen Server zuzuweisen. Wenn die Gruppe ihr `max_servers`-Limit erreicht hat, wird der eingereihte Start als `FAILED` mit einem Grund markiert.

### Eingereihte Starts auflisten

```java theme={null}
api.group().getServerStartQueue()
    .thenAccept(queue -> {
        System.out.println("Gruppen mit Queue-Daten: " + queue.getCount());
        System.out.println("Wartend: " + queue.getQueuedStarts());
        System.out.println("Fehlgeschlagen: " + queue.getFailedStarts());

        GroupStartQueueEntry lobby = queue.findByServerGroupName("lobby");
        if (lobby != null) {
            System.out.println("Lobby-Starts: " + lobby.getTotalStarts());
        }
    });
```

### Eingereihte Starts löschen

Alle ausstehenden und fehlgeschlagenen Starts einer bestimmten Gruppe entfernen:

```java theme={null}
api.group().clearServerStartQueue("group-uuid")
    .thenRun(() -> System.out.println("Warteschlange für group-uuid geleert"));
```

### Start-Warteschlangen-Übersicht

`getServerStartQueue()` gibt eine `GroupStartQueue` zurück.

<ResponseField name="count" type="integer" required>
  Anzahl der Gruppen mit Queue-Daten.
</ResponseField>

<ResponseField name="queuedStarts" type="integer" required>
  Anzahl wartender Starts über alle Gruppen.
</ResponseField>

<ResponseField name="failedStarts" type="integer" required>
  Anzahl fehlgeschlagener Starts über alle Gruppen.
</ResponseField>

<ResponseField name="totalStarts" type="integer" required>
  Gesamtzahl aller Queue-Einträge.
</ResponseField>

<ResponseField name="items" type="List<GroupStartQueueEntry>" required>
  Queue-Daten nach Server-Gruppe gruppiert.
</ResponseField>

### Queue-Eintrag pro Gruppe

<ResponseField name="serverGroupId" type="string | null">
  Server-Gruppen-ID.
</ResponseField>

<ResponseField name="serverGroupName" type="string | null">
  Server-Gruppenname.
</ResponseField>

<ResponseField name="queuedStarts" type="integer" required>
  Anzahl wartender Starts für die Gruppe.
</ResponseField>

<ResponseField name="failedStarts" type="integer" required>
  Anzahl fehlgeschlagener Starts für die Gruppe.
</ResponseField>

<ResponseField name="totalStarts" type="integer" required>
  Gesamtzahl der Queue-Einträge für die Gruppe.
</ResponseField>

<ResponseField name="starts" type="List<GroupStartQueueItem>" required>
  Persistierte Start-Anfragen für die Gruppe.
</ResponseField>

### Queue-Item

<ResponseField name="id" type="string" required>
  Eindeutige Kennung des eingereihten Starts.
</ResponseField>

<ResponseField name="createdAt" type="string | null">
  Zeitstempel der Einreihung im ISO-8601-Format.
</ResponseField>

<ResponseField name="status" type="GroupStartQueueItemStatus" required>
  Status des Queue-Items. Mögliche Werte sind `PENDING`, `FAILED` und `UNKNOWN`.
</ResponseField>

<ResponseField name="failureReason" type="string | null">
  Grund des Fehlschlags, falls zutreffend.
</ResponseField>

<Warning>
  Fehlgeschlagene Starts werden nach 1 Stunde automatisch bereinigt. Verwende den List-Endpunkt, um auf Fehler zu prüfen und bei Bedarf neu einzureihen.
</Warning>

## GroupServerType

| Wert     | Beschreibung                        |
| -------- | ----------------------------------- |
| `SERVER` | Game-Server (Paper, Spigot, etc.)   |
| `PROXY`  | Proxy-Server (Velocity, BungeeCord) |
