> ## 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.

# Server programmatisch verwalten

> Server mit der Cloud API anfordern, stoppen und überwachen

Diese Anleitung zeigt gängige Muster für die programmatische Server-Verwaltung.

## Server bei Bedarf anfordern

Server-Starts werden über die Groups API eingereiht. Das zurückgegebene Future ist abgeschlossen, sobald die Anfrage angenommen wurde, nicht sobald der neue Server bereit ist.

### Einzelnen Server anfordern

```java theme={null}
public CompletableFuture<Void> requestServerStart(String groupName) {
    return api.group().getGroupByName(groupName)
        .thenCompose(group -> {
            if (group == null) {
                return CompletableFuture.failedFuture(
                    new IllegalArgumentException("Gruppe nicht gefunden: " + groupName));
            }
            return api.group().requestServerStart(group);
        });
}
```

### Mehrere Server anfordern

```java theme={null}
public void ensureMinimumServers(String groupName, int minimum) {
    api.server().getServersByGroup(groupName).thenAccept(servers -> {
        long running = servers.stream()
            .filter(server -> server.getState() != ServerState.STOPPING)
            .filter(server -> server.getState() != ServerState.CLEANUP)
            .count();

        int toStart = Math.max(0, minimum - (int) running);
        for (int i = 0; i < toStart; i++) {
            requestServerStart(groupName)
                .thenRun(() -> System.out.println("Start-Anfrage angenommen: " + groupName));
        }
    });
}
```

## Server stoppen

### Einzelnen Server stoppen

```java theme={null}
public void stopServer(String serverId) {
    api.server().stopServer(serverId)
        .thenRun(() -> System.out.println("Stop angefragt: " + serverId));
}
```

### Leere Server stoppen

```java theme={null}
public void stopEmptyServers(String groupName, int keepMinimum) {
    api.server().getServersByGroup(groupName).thenAccept(servers -> {
        List<Server> emptyServers = servers.stream()
            .filter(server -> server.getState() == ServerState.AVAILABLE)
            .filter(server -> server.getPlayerCount() != null && server.getPlayerCount() == 0)
            .sorted(Comparator.comparingInt(Server::getNumericalId).reversed())
            .toList();

        int toStop = Math.max(0, emptyServers.size() - keepMinimum);

        emptyServers.stream()
            .limit(toStop)
            .forEach(server -> api.server().stopServer(server.getServerId()));
    });
}
```

### Graceful Shutdown mit Spieler-Evakuierung

```java theme={null}
public void gracefulStop(String serverId, String fallbackServer) {
    api.server().getServerById(serverId).thenAccept(server -> {
        if (server == null) return;

        api.player().getOnlinePlayers().thenAccept(players -> {
            List<CompletableFuture<CloudPlayer.ConnectResult>> transfers = players.stream()
                .filter(player -> serverId.equals(player.getConnectedServerName()))
                .map(player -> {
                    player.sendMessage(Component.text("Server fährt herunter...")
                        .color(NamedTextColor.YELLOW));
                    return player.connect(fallbackServer);
                })
                .toList();

            CompletableFuture.allOf(transfers.toArray(new CompletableFuture[0]))
                .thenRun(() -> api.server().stopServer(serverId));
        });
    });
}
```

## Server überwachen

### Server-Anzahl beobachten

```java theme={null}
public void monitorServerCount(String groupName) {
    api.event().server().onStarted(event -> {
        Server server = event.getServer();
        if (server.isFromGroup() && groupName.equals(server.getGroup().getName())) {
            updateServerCount(groupName);
        }
    });

    api.event().server().onStopped(event -> {
        Server server = event.getServer();
        if (server.isFromGroup() && groupName.equals(server.getGroup().getName())) {
            updateServerCount(groupName);
        }
    });
}

private void updateServerCount(String groupName) {
    api.server().getServersByGroup(groupName).thenAccept(servers -> {
        System.out.println(groupName + " Server: " + servers.size());
    });
}
```

## Server finden

### Server mit niedrigster Spielerzahl finden

```java theme={null}
public CompletableFuture<Server> findBestServer(String groupName) {
    return api.server().getServersByGroup(groupName)
        .thenApply(servers -> servers.stream()
            .filter(server -> server.getState() == ServerState.AVAILABLE ||
                server.getState() == ServerState.INGAME)
            .filter(server -> server.getPlayerCount() != null)
            .filter(server -> server.getPlayerCount() < server.getMaxPlayers())
            .min(Comparator.comparingInt(Server::getPlayerCount))
            .orElse(null));
}
```
