API Minecraft-серверов
Получайте игровые ники игроков, которые сейчас находятся на вашем сервере с клиентом Fantasy.
Один ключ — ваш список адресов. Ключ выдаёт команда Fantasy. Запрос возвращает только игровые ники в пределах выданного доступа. Регистрация аккаунта сама по себе доступ к API не открывает.
GET https://fantasyvisuals.cc/v1/server-api/players
1. Получите ключ для вашего сервера
Обратитесь к команде Fantasy, например на support@fantasyvisuals.cc. Сообщите название сервера, контакт владельца, назначение интеграции и все адреса, через которые заходят игроки: домены, IP и нестандартные порты.
После согласования вы получите ключ вида fsa_…. Сохраните его в приватном конфиге плагина или переменной окружения. Передавайте ключ только из серверной части по HTTPS. Не добавляйте его в мод клиента, Git, публичную веб-страницу или логи.
Адреса сопоставляются полностью, вместе с портом. mc.example.com и MC.EXAMPLE.COM.:25565 равнозначны. other.example.com, mc.example.net, IP и порт 25566 — отдельные адреса: каждый нужно согласовать. Поддерживаются ASCII-домены, IPv4 и IPv6 в квадратных скобках. Для IDN используйте punycode.
Ни домен, ни serverId передавать в запросе не нужно: сервер определяет доступ по ключу. Параметры URL не расширяют выданный доступ.
2. Проверьте запрос
Замените ВАШ_КЛЮЧ выданным ключом. Для первого запроса достаточно curl; вход в аккаунт Fantasy и браузерные cookie не нужны.
Linux и macOS
export FANTASY_SERVER_API_KEY='ВАШ_КЛЮЧ'
curl --silent --show-error --fail-with-body --max-time 5 \
-H "Authorization: Bearer $FANTASY_SERVER_API_KEY" \
https://fantasyvisuals.cc/v1/server-api/players
Windows PowerShell
$env:FANTASY_SERVER_API_KEY = 'ВАШ_КЛЮЧ'
curl.exe --silent --show-error --fail-with-body --max-time 5 `
-H "Authorization: Bearer $env:FANTASY_SERVER_API_KEY" `
https://fantasyvisuals.cc/v1/server-api/players
Успех — статус 200 и JSON. Для проверки с непустым списком зайдите на разрешённый адрес сервера с обновлённым клиентом Fantasy и повторите запрос через несколько секунд. 200 с пустым списком также является корректным ответом.
3. Прочитайте ответ
{
"serverId": "example-network",
"players": ["ActualGameNick", "Another_Player"],
"count": 2,
"generatedAt": "2026-10-29T09:00:00Z",
"freshSeconds": 15
}
| Поле | Тип | Значение |
|---|---|---|
serverId | string | Идентификатор сервера, назначенный при выдаче ключа. |
players | string[] | Игровые имена, уникальные без учёта регистра и отсортированные по имени. Это имя профиля Minecraft, а не ник аккаунта Fantasy и не оформленный ник из TAB. |
count | integer | Количество элементов в players. |
generatedAt | string | Время формирования снимка в UTC, формат ISO 8601. |
freshSeconds | integer | Окно свежести подтверждения игроком своего присутствия: 15 секунд. |
UUID, UID, HWID, аккаунты Fantasy, координаты и косметика через этот метод не выдаются. Неизвестные поля JSON игнорируйте, чтобы добавление полей не ломало ваш плагин.
4. Подключите запрос к плагину
- Читайте ключ из серверного конфига. Делайте запрос примерно раз в 5 секунд. Разделяйте один результат между всеми игроками сервера.
- Выполняйте HTTP асинхронно с таймаутом. Не блокируйте игровой поток и не делайте отдельный запрос на каждого игрока.
- При
200читайте массивplayersи сравнивайте ники без учёта регистра. - Пересекайте результат с локальным онлайном сервера. Для Bukkit, Spigot и Paper обращайтесь к игрокам и меняйте их состояние в основном потоке.
- При ошибке помечайте данные недоступными; старый успешный список не является текущим онлайном.
Пример для Java 21 и Bukkit, Spigot или Paper
Фрагмент для вашего класса JavaPlugin. Использует стандартный java.net.http.HttpClient и Gson для JSON; Gson должен быть зависимостью вашего плагина. Импорты: java.net.URI, java.net.http.*, java.time.Duration, java.util.*, java.util.concurrent.CompletableFuture, com.google.gson.JsonParser, org.bukkit.Bukkit, org.bukkit.entity.Player.
// Внутри вашего JavaPlugin. Для JSON здесь используется Gson.
private final HttpClient http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(2))
.build();
private CompletableFuture<Set<String>> loadFantasyPlayers(String apiKey) {
HttpRequest request = HttpRequest.newBuilder(
URI.create("https://fantasyvisuals.cc/v1/server-api/players"))
.timeout(Duration.ofSeconds(5))
.header("Authorization", "Bearer " + apiKey)
.GET()
.build();
return http.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(response -> {
if (response.statusCode() != 200) {
throw new IllegalStateException(
"Fantasy API HTTP " + response.statusCode());
}
var json = JsonParser.parseString(response.body()).getAsJsonObject();
Set<String> names = new HashSet<>();
for (var name : json.getAsJsonArray("players")) {
names.add(name.getAsString().toLowerCase(Locale.ROOT));
}
return Set.copyOf(names);
});
}
// Вызывать примерно раз в 5 секунд. apiKey читается из серверного конфига.
private void refreshFantasyPlayers(String apiKey) {
loadFantasyPlayers(apiKey).thenAccept(names ->
Bukkit.getScheduler().runTask(this, () -> {
Set<UUID> localFantasyPlayers = new HashSet<>();
for (Player player : Bukkit.getOnlinePlayers()) {
if (names.contains(player.getName().toLowerCase(Locale.ROOT))) {
localFantasyPlayers.add(player.getUniqueId());
}
}
// Примените localFantasyPlayers к вашим значкам/спискам.
})
).exceptionally(error -> {
// 401: проверить ключ; 429: снизить частоту; 503: повторить позже.
// Пометьте данные недоступными, не считайте старый список текущим.
return null;
});
}
Это пример интеграции, а не готовый устанавливаемый плагин. Запланируйте повторный вызов примерно каждые 100 тиков, сохраните результат для своей функции и обработайте завершение плагина. При использовании Folia перенесите применение результата на подходящий scheduler вашей платформы.
5. Обработайте ошибки и лимиты
| Статус | Что означает | Что делать |
|---|---|---|
200 | Запрос выполнен. | Обновить список. Пустой players допустим. |
401 | Ключ отсутствует, неверен, отозван или истёк. | Проверить заголовок Authorization: Bearer …, затем обратиться к команде Fantasy. Обычный токен аккаунта здесь не подходит. |
429 | Слишком частые запросы. | Выждать как минимум время из Retry-After (сейчас 1 секунда). Перейти к опросу раз в 5 секунд. |
503 | Источник присутствия временно недоступен. | Пометить данные недоступными и повторить позже. Это не ответ «все игроки вышли». |
Лимит — 1 запрос в секунду на ключ. Если ключ используют несколько плагинов или под-серверов, координируйте общий опрос либо запросите отдельные ключи. При сетевых ошибках используйте увеличивающуюся задержку, например 5 → 10 → 20 → 30 секунд; после успеха вернитесь к 5 секундам. Ответы имеют Cache-Control: no-store: не сохраняйте их как постоянную базу пользователей Fantasy.
Как определяется присутствие
Обновлённый клиент Fantasy подтверждает игровой ник и адрес, пока находится в загруженном многопользовательском мире. Подтверждения приходят примерно раз в 5 секунд при нормальной скорости тиков; вход и выход из мира сообщаются на следующем тике.
При обычном отключении соединение удаляется сразу. При потере связи подтверждение перестаёт считаться свежим через 15 секунд. Время формирования ответа не означает, что каждый игрок проверен в ту же миллисекунду.
Меню, одиночная игра и старые клиенты без нового признака присутствия не учитываются. После перезапуска сервиса список набирается заново. Убедитесь, что игрок установил актуальную версию Fantasy и подключён именно через один из согласованных адресов.
BungeeCord и Velocity
Адрес подключения к прокси обозначает всю сеть. API сам не различает её внутренние под-серверы. Чтобы получить игроков конкретного под-сервера, пересеките players с его локальным онлайном, как в примере выше.
Граница доверия. Присутствие сообщает аутентифицированный клиент; изменённый клиент может подменить сообщаемый адрес или ник. Используйте API для отображения признака Fantasy. Выдача прав, наград или проверка личности требуют отдельного подтверждения сессии игрока.
Управление доступом для администраторов Fantasy
Этот раздел нужен команде Fantasy. Владельцу Minecraft-сервера достаточно выданного Bearer-ключа и метода получения игроков.
Откройте админку → Система → API серверов и нажмите «Выдать доступ». Заполните идентификатор сервера, получателя, список адресов и при необходимости срок. После создания скопируйте ключ: он показывается один раз. В той же вкладке можно просмотреть выданные доступы и отозвать любой из них.
Выдача, просмотр и отзыв ключей
Методы требуют X-Session-Token действующего администратора Fantasy. При выдаче администратор проверяет принадлежность указанных адресов получателю.
POST https://fantasyvisuals.cc/v1/admin/server-api/keys
X-Session-Token: <ADMIN_SESSION>
Content-Type: application/json
{
"serverId": "example-network",
"label": "Владелец Example / основной плагин",
"addresses": ["mc.example.com", "play.example.net:25566"],
"expiresAt": "2027-01-01T00:00:00Z"
}
Ответ 201: { "key": "fsa_…", "info": { … } }. Полный ключ доступен только в этом ответе. expiresAt можно опустить. serverId — 1–64 символа: строчные латинские буквы, цифры, _ и -, первый символ — буква или цифра. Подпись label — 1–120 символов, адресов — 1–32.
GET /v1/admin/server-api/keys?page=0&size=50— метаданные без секретов,sizeот 1 до 100. Полеscopeсейчас равноminecraft.players.read.DELETE /v1/admin/server-api/keys/{id}— отзыв, ответ204. Следующий запрос с этим ключом получает401.
Для ротации создайте новый ключ, замените его в интеграции и отзовите старый. Разным получателям можно выдать отдельные ключи с одинаковыми адресами и отзывать их независимо.